PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/django/contrib/comments/models.py

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