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
):
16 An abstract base class that any custom comment models probably should
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")
27 # Metadata about the comment
28 site
= models
.ForeignKey(Site
)
33 def get_content_object_url(self
):
35 Get a URL suitable for redirecting to the content object.
37 return urlresolvers
.reverse(
38 "comments-url-redirect",
39 args
=(self
.content_type_id
, self
.object_pk
)
42 class Comment(BaseCommentAbstractModel
):
44 A user comment about some object.
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)
56 comment
= models
.TextField(_('comment'), max_length
=COMMENT_MAX_LENGTH
)
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.'))
70 objects
= CommentManager()
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')
79 def __unicode__(self
):
80 return "%s: %s..." % (self
.name
, self
.comment
[:50])
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
)
87 def _get_userinfo(self
):
89 Get a dictionary that pulls together information about the poster
90 safely for both authenticated and non-authenticated comments.
92 This dict will have ``name``, ``email``, and ``url`` fields.
94 if not hasattr(self
, "_userinfo"):
96 "name" : self
.user_name
,
97 "email" : self
.user_email
,
103 self
._userinfo
["email"] = u
.email
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
__)
116 return self
.userinfo
["name"]
117 def _set_name(self
, val
):
119 raise AttributeError(_("This comment was posted by an authenticated "\
120 "user and thus the name is read-only."))
122 name
= property(_get_name
, _set_name
, doc
="The name of the user who posted this comment")
124 def _get_email(self
):
125 return self
.userinfo
["email"]
126 def _set_email(self
, val
):
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")
134 return self
.userinfo
["url"]
135 def _set_url(self
, val
):
137 url
= property(_get_url
, _set_url
, doc
="The URL given by the user who posted this comment")
139 def get_absolute_url(self
, anchor_pattern
="#c%(id)s"):
140 return self
.get_content_object_url() + (anchor_pattern
% self
.__dict
__)
142 def get_as_text(self
):
144 Return this comment as plain text. Useful for emails.
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()
153 return _('Posted by %(user)s at %(date)s\n\n%(comment)s\n\nhttp://%(domain)s%(url)s') % d
155 class CommentFlag(models
.Model
):
157 Records a flag on a comment. This is intentionally flexible; right now, a
160 * A "removal suggestion" -- where a user suggests a comment for (potential) removal.
162 * A "moderator deletion" -- used when a moderator deletes a comment.
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.
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)
173 # Constants for flag types
174 SUGGEST_REMOVAL
= "removal suggestion"
175 MODERATOR_DELETION
= "moderator deletion"
176 MODERATOR_APPROVAL
= "moderator approval"
179 db_table
= 'django_comment_flags'
180 unique_together
= [('user', 'comment', 'flag')]
181 verbose_name
= _('comment flag')
182 verbose_name_plural
= _('comment flags')
184 def __unicode__(self
):
185 return "%s flag of comment ID %s by %s" % \
186 (self
.flag
, self
.comment_id
, self
.user
.username
)
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
)