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 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
)
32 def get_content_object_url(self
):
34 Get a URL suitable for redirecting to the content object.
36 return urlresolvers
.reverse(
37 "comments-url-redirect",
38 args
=(self
.content_type_id
, self
.object_pk
)
41 class Comment(BaseCommentAbstractModel
):
43 A user comment about some object.
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.'))
68 objects
= CommentManager()
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
):
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.
90 if not hasattr(self
, "_userinfo"):
92 "name" : self
.user_name
,
93 "email" : self
.user_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
__)
112 return self
.userinfo
["name"]
113 def _set_name(self
, val
):
115 raise AttributeError(_("This comment was posted by an authenticated "\
116 "user and thus the name is read-only."))
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
):
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")
130 return self
.userinfo
["url"]
131 def _set_url(self
, 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.
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
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"
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
)