class BaseCommentAbstractModel(models.Model): """ An abstract base class that any custom comment models probably should subclass. """ # Content-object field content_type = models.ForeignKey( ContentType, verbose_name=_('content type'), related_name="content_type_set_for_%(class)s") object_pk = models.TextField(_('object ID')) content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk") # Metadata about the comment site = models.ForeignKey(Site) class Meta: abstract = True def get_content_object_url(self): """ Get a URL suitable for redirecting to the content object. """ return urlresolvers.reverse("comments-url-redirect", args=(self.content_type_id, self.object_pk))
class LogEntry(models.Model): action_time = models.DateTimeField(_('action time'), auto_now=True) user = models.ForeignKey(User) content_type = models.ForeignKey(ContentType, blank=True, null=True) object_id = models.TextField(_('object id'), blank=True, null=True) object_repr = models.CharField(_('object repr'), max_length=200) action_flag = models.PositiveSmallIntegerField(_('action flag')) change_message = models.TextField(_('change message'), blank=True) objects = LogEntryManager() class Meta: verbose_name = _('log entry') verbose_name_plural = _('log entries') db_table = 'django_admin_log' ordering = ('-action_time', ) def __repr__(self): return smart_unicode(self.action_time) def __unicode__(self): if self.action_flag == ADDITION: return _('Added "%(object)s".') % {'object': self.object_repr} elif self.action_flag == CHANGE: return _('Changed "%(object)s" - %(changes)s') % { 'object': self.object_repr, 'changes': self.change_message } elif self.action_flag == DELETION: return _('Deleted "%(object)s."') % {'object': self.object_repr} return _('LogEntry Object') def is_addition(self): return self.action_flag == ADDITION def is_change(self): return self.action_flag == CHANGE def is_deletion(self): return self.action_flag == DELETION def get_edited_object(self): "Returns the edited object represented by this log entry" return self.content_type.get_object_for_this_type(pk=self.object_id) def get_admin_url(self): """ Returns the admin URL to edit the object represented by this log entry. This is relative to the Django admin index page. """ if self.content_type and self.object_id: return mark_safe(u"%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, quote(self.object_id))) return None
class RepositoryUser(models.Model): """A User of a repository""" source_repository = models.ForeignKey(HgRepository) user = models.ForeignKey(User) permission = models.IntegerField(_('Permission'), choices=PERM_CHOICES) def __unicode__(self): out = u"%s of %s with %s permission" % ( self.user, self.source_repository, self.get_permission_display()) return out
class Topic(models.Model): forum = models.ForeignKey(Forum) subject = models.CharField(u'Тема', max_length=255) created = models.DateTimeField(default=datetime.now, db_index=True) deleted = models.DateTimeField(null=True, db_index=True) spam_status = models.CharField(max_length=20, default='clean') # -- is_forum = models.BooleanField(default=True) objects = TopicManager() deleted_objects = DeletedTopicManager() class Meta: ordering = ['-id'] def __unicode__(self): return self.subject def delete(self): Article.deleted_objects.filter(topic=self).delete() super(Topic, self).delete() @models.permalink def get_absolute_url(self): return 'cicero.views.topic', [self.forum.slug, self.id] def old(self): return self.created.date() < datetime.now().date() - timedelta( settings.CICERO_OLD_TOPIC_AGE)
class Redirect(models.Model): site = models.ForeignKey(Site) old_path = models.CharField( _('redirect from'), max_length=200, db_index=True, help_text= _("This should be an absolute path, excluding the domain name. Example: '/events/search/'." )) new_path = models.CharField( _('redirect to'), max_length=200, blank=True, help_text= _("This can be either an absolute path (as above) or a full URL starting with 'http://'." )) class Meta: verbose_name = _('redirect') verbose_name_plural = _('redirects') db_table = 'django_redirect' unique_together = (('site', 'old_path'), ) ordering = ('old_path', ) def __unicode__(self): return "%s ---> %s" % (self.old_path, self.new_path)
class CommentFlag(models.Model): """ Records a flag on a comment. This is intentionally flexible; right now, a flag could be: * A "removal suggestion" -- where a user suggests a comment for (potential) removal. * A "moderator deletion" -- used when a moderator deletes a comment. You can (ab)use this model to add other flags, if needed. However, by design users are only allowed to flag a comment with a given flag once; if you want rating look elsewhere. """ user = models.ForeignKey(User, verbose_name=_('user'), related_name="comment_flags") comment = models.ForeignKey(Comment, verbose_name=_('comment'), related_name="flags") flag = models.CharField(_('flag'), max_length=30, db_index=True) flag_date = models.DateTimeField(_('date'), default=None) # Constants for flag types SUGGEST_REMOVAL = "removal suggestion" MODERATOR_DELETION = "moderator deletion" MODERATOR_APPROVAL = "moderator approval" class Meta: db_table = 'django_comment_flags' unique_together = [('user', 'comment', 'flag')] verbose_name = _('comment flag') verbose_name_plural = _('comment flags') def __unicode__(self): return "%s flag of comment ID %s by %s" % \ (self.flag, self.comment_id, self.user.username) def save(self, *args, **kwargs): if self.flag_date is None: self.flag_date = timezone.now() super(CommentFlag, self).save(*args, **kwargs)
def sql_for_inline_many_to_many_references(self, model, field, style): from my_django.db import models opts = model._meta qn = self.connection.ops.quote_name table_output = [ ' %s %s %s,' % (style.SQL_FIELD(qn(field.m2m_column_name())), style.SQL_COLTYPE( models.ForeignKey(model).db_type(connection=self.connection)), style.SQL_KEYWORD('NOT NULL')), ' %s %s %s,' % (style.SQL_FIELD(qn(field.m2m_reverse_name())), style.SQL_COLTYPE( models.ForeignKey( field.rel.to).db_type(connection=self.connection)), style.SQL_KEYWORD('NOT NULL')) ] deferred = [(field.m2m_db_table(), field.m2m_column_name(), opts.db_table, opts.pk.column), (field.m2m_db_table(), field.m2m_reverse_name(), field.rel.to._meta.db_table, field.rel.to._meta.pk.column) ] return table_output, deferred
class Permission(models.Model): """ The permissions system provides a way to assign permissions to specific users and groups of users. The permission system is used by the Django admin site, but may also be useful in your own code. The Django admin site uses permissions as follows: - The "add" permission limits the user's ability to view the "add" form and add an object. - The "change" permission limits a user's ability to view the change list, view the "change" form and change an object. - The "delete" permission limits the ability to delete an object. Permissions are set globally per type of object, not per specific object instance. It is possible to say "Mary may change news stories," but it's not currently possible to say "Mary may change news stories, but only the ones she created herself" or "Mary may only change news stories that have a certain status or publication date." Three basic permissions -- add, change and delete -- are automatically created for each Django model. """ name = models.CharField(_('name'), max_length=50) content_type = models.ForeignKey(ContentType) codename = models.CharField(_('codename'), max_length=100) objects = PermissionManager() class Meta: verbose_name = _('permission') verbose_name_plural = _('permissions') unique_together = (('content_type', 'codename'), ) ordering = ('content_type__app_label', 'content_type__model', 'codename') def __unicode__(self): return u"%s | %s | %s" % (unicode( self.content_type.app_label), unicode( self.content_type), unicode(self.name)) def natural_key(self): return (self.codename, ) + self.content_type.natural_key() natural_key.dependencies = ['contenttypes.contenttype']
class Comment(BaseCommentAbstractModel): """ A user comment about some object. """ # Who posted this comment? If ``user`` is set then it was an authenticated # user; otherwise at least user_name should have been set and the comment # was posted by a non-authenticated user. user = models.ForeignKey(User, verbose_name=_('user'), blank=True, null=True, related_name="%(class)s_comments") user_name = models.CharField(_("user's name"), max_length=50, blank=True) user_email = models.EmailField(_("user's email address"), blank=True) user_url = models.URLField(_("user's URL"), blank=True) comment = models.TextField(_('comment'), max_length=COMMENT_MAX_LENGTH) # Metadata about the comment submit_date = models.DateTimeField(_('date/time submitted'), default=None) ip_address = models.IPAddressField(_('IP address'), blank=True, null=True) is_public = models.BooleanField(_('is public'), default=True, help_text=_('Uncheck this box to make the comment effectively ' \ 'disappear from the site.')) is_removed = models.BooleanField(_('is removed'), default=False, help_text=_('Check this box if the comment is inappropriate. ' \ 'A "This comment has been removed" message will ' \ 'be displayed instead.')) # Manager objects = CommentManager() class Meta: db_table = "django_comments" ordering = ('submit_date', ) permissions = [("can_moderate", "Can moderate comments")] verbose_name = _('comment') verbose_name_plural = _('comments') def __unicode__(self): return "%s: %s..." % (self.name, self.comment[:50]) def save(self, *args, **kwargs): if self.submit_date is None: self.submit_date = timezone.now() super(Comment, self).save(*args, **kwargs) def _get_userinfo(self): """ Get a dictionary that pulls together information about the poster safely for both authenticated and non-authenticated comments. This dict will have ``name``, ``email``, and ``url`` fields. """ if not hasattr(self, "_userinfo"): self._userinfo = { "name": self.user_name, "email": self.user_email, "url": self.user_url } if self.user_id: u = self.user if u.email: self._userinfo["email"] = u.email # If the user has a full name, use that for the user name. # However, a given user_name overrides the raw user.username, # so only use that if this comment has no associated name. if u.get_full_name(): self._userinfo["name"] = self.user.get_full_name() elif not self.user_name: self._userinfo["name"] = u.username return self._userinfo userinfo = property(_get_userinfo, doc=_get_userinfo.__doc__) def _get_name(self): return self.userinfo["name"] def _set_name(self, val): if self.user_id: raise AttributeError(_("This comment was posted by an authenticated "\ "user and thus the name is read-only.")) self.user_name = val name = property(_get_name, _set_name, doc="The name of the user who posted this comment") def _get_email(self): return self.userinfo["email"] def _set_email(self, val): if self.user_id: raise AttributeError(_("This comment was posted by an authenticated "\ "user and thus the email is read-only.")) self.user_email = val email = property(_get_email, _set_email, doc="The email of the user who posted this comment") def _get_url(self): return self.userinfo["url"] def _set_url(self, val): self.user_url = val url = property(_get_url, _set_url, doc="The URL given by the user who posted this comment") def get_absolute_url(self, anchor_pattern="#c%(id)s"): return self.get_content_object_url() + (anchor_pattern % self.__dict__) def get_as_text(self): """ Return this comment as plain text. Useful for emails. """ d = { 'user': self.user or self.name, 'date': self.submit_date, 'comment': self.comment, 'domain': self.site.domain, 'url': self.get_absolute_url() } return _( 'Posted by %(user)s at %(date)s\n\n%(comment)s\n\nhttp://%(domain)s%(url)s' ) % d
class Comment(models.Model): repo = models.ForeignKey(Repo, on_delete=models.CASCADE) rev = models.CharField(max_length=200)#tag file_path = models.CharField(max_length=200)#tag line = models.IntegerField() content = models.CharField(max_length=200)
class Article(models.Model): topic = models.ForeignKey(Topic) text = models.TextField(u'Текст') filter = models.CharField(u'Фильтр', max_length=50, choices=[(k, k) for k in filters.keys()]) created = models.DateTimeField(default=datetime.now, db_index=True) updated = models.DateTimeField(auto_now=True, db_index=True) author = models.ForeignKey(Profile) guest_name = models.CharField(max_length=255, blank=True) deleted = models.DateTimeField(null=True, db_index=True) spawned_to = models.OneToOneField(Topic, null=True, related_name='spawned_from') spam_status = models.CharField(max_length=20, default='clean') ip = models.IPAddressField(default='127.0.0.1') # -- is_forum = models.BooleanField(default=True) objects = ArticleManager() deleted_objects = DeletedArticleManager() class Meta: ordering = ['created'] def __unicode__(self): #return u"topic: %s, author: %s, created: %s" % (self.topic, self.author, self.created) #.replace(microsecond=0)) return u"{topic: %s, author: %s, created: %s}" % ( self.topic, self.author, self.created.replace(microsecond=0)) #return 'topic': self.topic, 'author': self.author, 'created': self.created} def delete(self): topic = self.topic super(Article, self).delete() if topic.article_set.count() == 0: topic.delete() def html(self): ''' Возвращает HTML-текст статьи, полученный фильтрацией содержимого через указанный фильтр. ''' if self.filter in filters: result = filters[self.filter](self.text) else: result = linebreaks(escape(self.text)) return mark_safe(result) soup = BeautifulSoup(result) def urlify(s): s = re.sub(WWW_PATTERN, r'\1http://www.', s) s = re.sub(FTP_PATTERN, r'\1ftp://ftp.', s) s = re.sub(PROTOCOL_PATTERN, r'<a href="\1\2">\1\2</a>\3\4', s) return BeautifulSoup(s) def has_parents(node, tags): if node is None: return False return node.name in tags or has_parents(node.parent, tags) text_chunks = [ c for c in soup.recursiveChildGenerator() if isinstance(c, unicode) ] for chunk in text_chunks: s = chunk if not has_parents(chunk.parent, ['code']): s = re.sub(ur'\B--\B', u'—', s) if not has_parents(chunk.parent, ['a', 'code']): s = urlify(s) chunk.replaceWith(s) for link in soup.findAll('a'): if 'rel' in link: link['rel'] += ' ' else: link['rel'] = '' link['rel'] += 'nofollow' result = unicode(soup) return mark_safe(result) def from_guest(self): ''' Была ли написана статья от имени гостя. Используется, в основном, в шаблонах. ''' return self.author.user == 'cicero_guest' def spawned(self): ''' Перенесена ли статья в новый топик. ''' return self.spawned_to_id is not None def ping_external_links(self): ''' Пингование внешних ссылок через Pingback (http://www.hixie.ch/specs/pingback/pingback) ''' domain = Site.objects.get_current().domain index_url = reverse('cicero_index') topic_url = utils.absolute_url( reverse('cicero.views.topic', args=(self.topic.forum.slug, self.topic.id))) def is_external(url): scheme, server, path, query, fragment = urlsplit(url) return server != '' and \ (server != domain or not path.startswith(index_url)) def search_link(content): match = re.search(r'<link rel="pingback" href="([^"]+)" ?/?>', content) return match and match.group(1) soup = BeautifulSoup(self.html()) links = (a['href'] for a in soup.findAll('a') if is_external(a['href'])) links = (l.encode('utf-8') for l in links) for link in links: try: f = urlopen(link) try: info = f.info() server_url = info.get('X-Pingback', '') or \ search_link(f.read(512 * 1024)) if server_url: server = ServerProxy(server_url) server.pingback.ping(topic_url, link) finally: f.close() except (IOError, Fault, ProtocolError, ResponseError, ExpatError): pass def set_spam_status(self, spam_status): ''' Проставляет статус спамности, поправляя, если надо, аналогичный статус топика. Сохраняет результат в базу. ''' if self.spam_status == spam_status: return self.spam_status = spam_status self.save() if self.topic.spam_status != spam_status and self.topic.article_set.count( ) == 1: self.topic.spam_status = spam_status self.topic.save()