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