PageRenderTime 13ms CodeModel.GetById 2ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

Plain Text | 286 lines | 219 code | 67 blank | 0 comment | 0 complexity | a1acb2371a211f930688066e6accd776 MD5 | raw file
  2Generic comment moderation
  5Django's bundled comments application is extremely useful on its own,
  6but the amount of comment spam circulating on the Web today
  7essentially makes it necessary to have some sort of automatic
  8moderation system in place for any application which makes use of
  9comments. To make this easier to handle in a consistent fashion,
 10``comment_utils`` provides a generic, extensible comment-moderation
 11system which can be applied to any model or set of models which want
 12to make use of Django's comment system.
 18The entire system is contained within ``comment_utils.moderation``,
 19and uses a two-step process to enable moderation for any given model:
 211. A subclass of ``comment_utils.moderation.CommentModerator`` is
 22   defined which specifies the moderation options the model wants to
 23   enable.
 252. The model is registered with the moderation system, passing in the
 26   model class and the class which specifies its moderation options.
 28A simple example is the best illustration of this. Suppose we have the
 29following model, which would represent entries in a weblog::
 31    from django.db import models
 33    class Entry(models.Model):
 34        title = models.CharField(maxlength=250)
 35        body = models.TextField()
 36        pub_date = models.DateTimeField()
 37        enable_comments = models.BooleanField()
 39Now, suppose that we want the following steps to be applied whenever a
 40new comment is posted on an ``Entry``:
 421. If the ``Entry``'s ``enable_comments`` field is ``False``, the
 43   comment will simply be disallowed (i.e., immediately deleted).
 452. If the ``enable_comments`` field is ``True``, the comment will be
 46   allowed to save, but will first be submitted to an Akismet spam
 47   check and have its ``is_public`` field set to ``False`` if Akismet
 48   thinks the comment is spam.
 503. Once the comment is saved, an email should be sent to site staff
 51   notifying them of the new comment.
 53Accomplishing this is fairly straightforward and requires very little
 56    from comment_utils.moderation import CommentModerator, moderator
 58    class EntryModerator(CommentModerator):
 59        akismet = True
 60        email_notification = True
 61        enable_field = 'enable_comments'
 63    moderator.register(Entry, EntryModerator)
 65The ``CommentModerator`` class pre-defines a number of useful
 66moderation options which subclasses can enable or disable as desired,
 67and ``moderator`` knows how to work with them to determine whether to
 68allow a comment, whether to moderate a comment which will be allowed
 69to post, and whether to email notifications of new comments.
 72Built-in moderation options
 75Most common comment-moderation needs can be handled by subclassing
 76``CommentModerator`` and changing the values of pre-defined
 77attributes; the full range of built-in options is as follows::
 79    ``akismet``
 80        If ``True``, comments will be submitted to an Akismet spam
 81        check and, if Akismet thinks they're spam, will have their
 82        ``is_public`` field set to ``False`` before saving. If this is
 83        enabled, you will need to have the Python Akismet module
 84        installed, and you will need to add the setting
 85        ``AKISMET_API_KEY`` to your Django settings file; the value of
 86        this setting should be a valid Akismet API key. Default value
 87        is ``False``.
 89    ``auto_close_field``
 90        If this is set to the name of a ``DateField`` or
 91        ``DateTimeField`` on the model for which comments are being
 92        moderated, new comments for objects of that model will be
 93        disallowed (immediately deleted) when a certain number of days
 94        have passed after the date specified in that field. Must be
 95        used in conjunction with ``close_after``, which specifies the
 96        number of days past which comments should be
 97        disallowed. Default value is ``None``.
 99    ``auto_moderate_field``
100        Like ``auto_close_field``, but instead of outright deleting
101        new comments when the requisite number of days have elapsed,
102        it will simply set the ``is_public`` field of new comments to
103        ``False`` before saving them. Must be used in conjunction with
104        ``moderate_after``, which specifies the number of days past
105        which comments should be moderated. Default value is ``None``.
107    ``close_after``
108        If ``auto_close_field`` is used, this must specify the number
109        of days past the value of the field specified by
110        ``auto_close_field`` after which new comments for an object
111        should be disallowed. Default value is ``None``.
113    ``email_notification``
114        If ``True``, any new comment on an object of this model which
115        survives moderation (i.e., is not deleted) will generate an
116        email to site staff. Default value is ``False``.
118    ``enable_field``
119        If this is set to the name of a ``BooleanField`` on the model
120        for which comments are being moderated, new comments on
121        objects of that model will be disallowed (immediately deleted)
122        whenever the value of that field is ``False`` on the object
123        the comment would be attached to. Default value is ``None``.
125    ``moderate_after``
126        If ``auto_moderate`` is used, this must specify the number of
127        days past the value of the field specified by
128        ``auto_moderate_field`` after which new comments for an object
129        should be marked non-public. Default value is ``None``.
131Simply subclassing ``CommentModerator`` and changing the values of
132these options will automatically enable the various moderation methods
133for any models registered using the subclass.
136Adding custom moderation methods
139For situations where the built-in options listed above are not
140sufficient, subclasses of ``CommentModerator`` can also override the
141methods which actually perform the moderation, and apply any logic
142they desire. ``CommentModerator`` defines three methods which
143determine how moderation will take place; each method will be called
144by the moderation system and passed two arguments: ``comment``, which
145is the new comment being posted, and ``content_object``, which is the
146object the comment will be attached to::
148    ``allow``
149        Should return ``True`` if the comment should be allowed to
150        post on the content object, and ``False`` otherwise (in which
151        case the comment will be immediately deleted).
153    ``email``
154        If email notification of the new comment should be sent to
155        site staff or moderators, this method is responsible for
156        sending the email.
158    ``moderate``
159        Should return ``True`` if the comment should be moderated (in
160        which case its ``is_public`` field will be set to ``False``
161        before saving), and ``False`` otherwise (in which case the
162        ``is_public`` field will not be changed).
165Built-in subclasses of ``CommentModerator``
168In order to make common cases simpler, and to provide examples of how
169``CommentModerator`` can be adapted to various types of moderation,
170three subclasses are included which set up different moderation
173    ``AkismetModerator``
174        Applies an Akismet spam check to all new comments for the
175        model on which it is used.
177    ``AlwaysModerate``
178        Forces all new comments for its model into moderation (by
179        setting ``is_public=False``).
181    ``ModerateFirstTimers``
182        Automatically moderates all comments from anyone who has not
183        previously had a comment approved, while allowing all other
184        comments to skip moderation.
187Registering models for moderation
190The moderation system, represented by
191``comment_utils.moderation.moderator`` is an instance of the class
192``comment_utils.moderation.Moderator``, which allows registration and
193"unregistration" of models via two methods::
195    ``register``
196        Takes two arguments: the first should be either a model class
197        or list of model classes, and the second should be a subclass
198        of ``CommentModerator``, and register the model or models to
199        be moderated using the options defined in the
200        ``CommentModerator`` subclass. If any of the models are
201        already registered for moderation, the exception
202        ``comment_utils.moderation.AlreadyModerated`` will be raised.
204    ``unregister``
205        Takes one argument: a model class or list of model classes,
206        and removes the model or models from the set of models which
207        are being moderated. If any of the models are not currently
208        being moderated, the exception
209        ``comment_utils.moderation.NotModerated`` will be raised.
212Customizing the moderation system
215Most use cases will work easily with simple subclassing of
216``CommentModerator`` and registration with the provided ``moderator``
217instance, but customization of global moderation behavior can be
218achieved by subclassing ``Moderator`` and instead registering models
219with an instance of the subclass.
221In addition to the ``register`` and ``unregister`` methods detailed
222above, the following methods on ``Moderator`` can be overridden to
223achieve customized behavior::
225    ``connect``
226        Determines how moderation is set up globally. The base
227        implementation in ``Moderator`` does this by attaching
228        listeners to the ``pre_save`` and ``post_save`` signals from
229        the comment models.
231    ``pre_save_moderation``
232        In the base implementation, applies all pre-save moderation
233        steps (such as determining whether the comment needs to be
234        deleted, or whether it needs to be marked as non-public or
235        generate an email).
237    ``post_save_moderation``
238        In the base implementation, applies all post-save moderation
239        steps (currently this consists entirely of deleting comments
240        which were disallowed).
243Automatically deleting non-public comments
246In order to save the hassle of manually deleting spam or
247otherwise-non-public comments on a regular basis, a script is included
248-- ``bin/`` -- which is intended to be used as
249a cron job, and which will automatically delete non-public comments
250based on criteria you provide to it.
252**Required arguments**
254``-s``, ``--settings``
255    Specifies the Django settings module to use.
258**Optional arguments**
260``-a`` ``--age``
261    An age cutoff, in days, beyond which non-public comments will be
262    deleted. for example, when using ``--age=7`` any non-public
263    comment older than 7 days will be deleted. Defaults to 14 if not
264    specified.
266``-d``, ``--dry-run``
267    Prints the number of comments which would have been deleted, but
268    does not actually delete them.
270``-t``, ``--type``
271    The type of comment to delete; ``--type=free`` will delete
272    instance of ``FreeComment``, ``--type=registered`` will delete
273    instances of ``Comment``. Defaults to "free" if not specified.
275``-v``, ``--verbose``
276    If supplied, the script will run verbosely, printing a description
277    of each comment as it is deleted. Regardless of the value of this
278    argument, the script will print the total number of deleted
279    comments once it is finished.
281So, for example, the script could be used like so::
283    ``python /path/to/comment_utils/bin/ --settings=mysite.settings --age=7 --type=registered
285This would delete every non-public ``Comment`` in the ``mysite``
286database older than 7 days.