web/lib/django/contrib/comments/models.py
changeset 38 77b6da96e6f1
equal deleted inserted replaced
37:8d941af65caf 38:77b6da96e6f1
       
     1 import datetime
       
     2 from django.contrib.auth.models import User
       
     3 from django.contrib.comments.managers import CommentManager
       
     4 from django.contrib.contenttypes import generic
       
     5 from django.contrib.contenttypes.models import ContentType
       
     6 from django.contrib.sites.models import Site
       
     7 from django.db import models
       
     8 from django.core import urlresolvers
       
     9 from django.utils.translation import ugettext_lazy as _
       
    10 from django.conf import settings
       
    11 
       
    12 COMMENT_MAX_LENGTH = getattr(settings,'COMMENT_MAX_LENGTH',3000)
       
    13 
       
    14 class BaseCommentAbstractModel(models.Model):
       
    15     """
       
    16     An abstract base class that any custom comment models probably should
       
    17     subclass.
       
    18     """
       
    19 
       
    20     # Content-object field
       
    21     content_type   = models.ForeignKey(ContentType,
       
    22             verbose_name=_('content type'),
       
    23             related_name="content_type_set_for_%(class)s")
       
    24     object_pk      = models.TextField(_('object ID'))
       
    25     content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")
       
    26 
       
    27     # Metadata about the comment
       
    28     site        = models.ForeignKey(Site)
       
    29 
       
    30     class Meta:
       
    31         abstract = True
       
    32 
       
    33     def get_content_object_url(self):
       
    34         """
       
    35         Get a URL suitable for redirecting to the content object.
       
    36         """
       
    37         return urlresolvers.reverse(
       
    38             "comments-url-redirect",
       
    39             args=(self.content_type_id, self.object_pk)
       
    40         )
       
    41 
       
    42 class Comment(BaseCommentAbstractModel):
       
    43     """
       
    44     A user comment about some object.
       
    45     """
       
    46 
       
    47     # Who posted this comment? If ``user`` is set then it was an authenticated
       
    48     # user; otherwise at least user_name should have been set and the comment
       
    49     # was posted by a non-authenticated user.
       
    50     user        = models.ForeignKey(User, verbose_name=_('user'),
       
    51                     blank=True, null=True, related_name="%(class)s_comments")
       
    52     user_name   = models.CharField(_("user's name"), max_length=50, blank=True)
       
    53     user_email  = models.EmailField(_("user's email address"), blank=True)
       
    54     user_url    = models.URLField(_("user's URL"), blank=True)
       
    55 
       
    56     comment = models.TextField(_('comment'), max_length=COMMENT_MAX_LENGTH)
       
    57 
       
    58     # Metadata about the comment
       
    59     submit_date = models.DateTimeField(_('date/time submitted'), default=None)
       
    60     ip_address  = models.IPAddressField(_('IP address'), blank=True, null=True)
       
    61     is_public   = models.BooleanField(_('is public'), default=True,
       
    62                     help_text=_('Uncheck this box to make the comment effectively ' \
       
    63                                 'disappear from the site.'))
       
    64     is_removed  = models.BooleanField(_('is removed'), default=False,
       
    65                     help_text=_('Check this box if the comment is inappropriate. ' \
       
    66                                 'A "This comment has been removed" message will ' \
       
    67                                 'be displayed instead.'))
       
    68 
       
    69     # Manager
       
    70     objects = CommentManager()
       
    71 
       
    72     class Meta:
       
    73         db_table = "django_comments"
       
    74         ordering = ('submit_date',)
       
    75         permissions = [("can_moderate", "Can moderate comments")]
       
    76         verbose_name = _('comment')
       
    77         verbose_name_plural = _('comments')
       
    78 
       
    79     def __unicode__(self):
       
    80         return "%s: %s..." % (self.name, self.comment[:50])
       
    81 
       
    82     def save(self, *args, **kwargs):
       
    83         if self.submit_date is None:
       
    84             self.submit_date = datetime.datetime.now()
       
    85         super(Comment, self).save(*args, **kwargs)
       
    86 
       
    87     def _get_userinfo(self):
       
    88         """
       
    89         Get a dictionary that pulls together information about the poster
       
    90         safely for both authenticated and non-authenticated comments.
       
    91 
       
    92         This dict will have ``name``, ``email``, and ``url`` fields.
       
    93         """
       
    94         if not hasattr(self, "_userinfo"):
       
    95             self._userinfo = {
       
    96                 "name"  : self.user_name,
       
    97                 "email" : self.user_email,
       
    98                 "url"   : self.user_url
       
    99             }
       
   100             if self.user_id:
       
   101                 u = self.user
       
   102                 if u.email:
       
   103                     self._userinfo["email"] = u.email
       
   104 
       
   105                 # If the user has a full name, use that for the user name.
       
   106                 # However, a given user_name overrides the raw user.username,
       
   107                 # so only use that if this comment has no associated name.
       
   108                 if u.get_full_name():
       
   109                     self._userinfo["name"] = self.user.get_full_name()
       
   110                 elif not self.user_name:
       
   111                     self._userinfo["name"] = u.username
       
   112         return self._userinfo
       
   113     userinfo = property(_get_userinfo, doc=_get_userinfo.__doc__)
       
   114 
       
   115     def _get_name(self):
       
   116         return self.userinfo["name"]
       
   117     def _set_name(self, val):
       
   118         if self.user_id:
       
   119             raise AttributeError(_("This comment was posted by an authenticated "\
       
   120                                    "user and thus the name is read-only."))
       
   121         self.user_name = val
       
   122     name = property(_get_name, _set_name, doc="The name of the user who posted this comment")
       
   123 
       
   124     def _get_email(self):
       
   125         return self.userinfo["email"]
       
   126     def _set_email(self, val):
       
   127         if self.user_id:
       
   128             raise AttributeError(_("This comment was posted by an authenticated "\
       
   129                                    "user and thus the email is read-only."))
       
   130         self.user_email = val
       
   131     email = property(_get_email, _set_email, doc="The email of the user who posted this comment")
       
   132 
       
   133     def _get_url(self):
       
   134         return self.userinfo["url"]
       
   135     def _set_url(self, val):
       
   136         self.user_url = val
       
   137     url = property(_get_url, _set_url, doc="The URL given by the user who posted this comment")
       
   138 
       
   139     def get_absolute_url(self, anchor_pattern="#c%(id)s"):
       
   140         return self.get_content_object_url() + (anchor_pattern % self.__dict__)
       
   141 
       
   142     def get_as_text(self):
       
   143         """
       
   144         Return this comment as plain text.  Useful for emails.
       
   145         """
       
   146         d = {
       
   147             'user': self.user or self.name,
       
   148             'date': self.submit_date,
       
   149             'comment': self.comment,
       
   150             'domain': self.site.domain,
       
   151             'url': self.get_absolute_url()
       
   152         }
       
   153         return _('Posted by %(user)s at %(date)s\n\n%(comment)s\n\nhttp://%(domain)s%(url)s') % d
       
   154 
       
   155 class CommentFlag(models.Model):
       
   156     """
       
   157     Records a flag on a comment. This is intentionally flexible; right now, a
       
   158     flag could be:
       
   159 
       
   160         * A "removal suggestion" -- where a user suggests a comment for (potential) removal.
       
   161 
       
   162         * A "moderator deletion" -- used when a moderator deletes a comment.
       
   163 
       
   164     You can (ab)use this model to add other flags, if needed. However, by
       
   165     design users are only allowed to flag a comment with a given flag once;
       
   166     if you want rating look elsewhere.
       
   167     """
       
   168     user      = models.ForeignKey(User, verbose_name=_('user'), related_name="comment_flags")
       
   169     comment   = models.ForeignKey(Comment, verbose_name=_('comment'), related_name="flags")
       
   170     flag      = models.CharField(_('flag'), max_length=30, db_index=True)
       
   171     flag_date = models.DateTimeField(_('date'), default=None)
       
   172 
       
   173     # Constants for flag types
       
   174     SUGGEST_REMOVAL = "removal suggestion"
       
   175     MODERATOR_DELETION = "moderator deletion"
       
   176     MODERATOR_APPROVAL = "moderator approval"
       
   177 
       
   178     class Meta:
       
   179         db_table = 'django_comment_flags'
       
   180         unique_together = [('user', 'comment', 'flag')]
       
   181         verbose_name = _('comment flag')
       
   182         verbose_name_plural = _('comment flags')
       
   183 
       
   184     def __unicode__(self):
       
   185         return "%s flag of comment ID %s by %s" % \
       
   186             (self.flag, self.comment_id, self.user.username)
       
   187 
       
   188     def save(self, *args, **kwargs):
       
   189         if self.flag_date is None:
       
   190             self.flag_date = datetime.datetime.now()
       
   191         super(CommentFlag, self).save(*args, **kwargs)