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))
示例#2
0
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
示例#4
0
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)
示例#5
0
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)
示例#7
0
    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)
示例#11
0
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()