2009-03-23 21:22:31 +00:00
|
|
|
==========================
|
|
|
|
Generic comment moderation
|
|
|
|
==========================
|
|
|
|
|
|
|
|
.. module:: django.contrib.comments.moderation
|
|
|
|
:synopsis: Support for automatic comment moderation.
|
|
|
|
|
|
|
|
Django's bundled comments application is extremely useful on its own,
|
|
|
|
but the amount of comment spam circulating on the Web today
|
|
|
|
essentially makes it necessary to have some sort of automatic
|
|
|
|
moderation system in place for any application which makes use of
|
|
|
|
comments. To make this easier to handle in a consistent fashion,
|
2009-05-14 15:20:50 +00:00
|
|
|
``django.contrib.comments.moderation`` provides a generic, extensible
|
|
|
|
comment-moderation system which can be applied to any model or set of
|
|
|
|
models which want to make use of Django's comment system.
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
Overview
|
|
|
|
========
|
|
|
|
|
|
|
|
The entire system is contained within ``django.contrib.comments.moderation``,
|
|
|
|
and uses a two-step process to enable moderation for any given model:
|
|
|
|
|
|
|
|
1. A subclass of :class:`CommentModerator`
|
|
|
|
is defined which specifies the moderation options the model wants to
|
|
|
|
enable.
|
|
|
|
|
|
|
|
2. The model is registered with the moderation system, passing in the
|
|
|
|
model class and the class which specifies its moderation options.
|
|
|
|
|
|
|
|
A simple example is the best illustration of this. Suppose we have the
|
2010-10-09 08:12:50 +00:00
|
|
|
following model, which would represent entries in a Weblog::
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
from django.db import models
|
2012-09-08 15:00:04 +00:00
|
|
|
|
2009-03-23 21:22:31 +00:00
|
|
|
class Entry(models.Model):
|
|
|
|
title = models.CharField(maxlength=250)
|
|
|
|
body = models.TextField()
|
2012-09-08 15:00:04 +00:00
|
|
|
pub_date = models.DateField()
|
2009-03-23 21:22:31 +00:00
|
|
|
enable_comments = models.BooleanField()
|
|
|
|
|
|
|
|
Now, suppose that we want the following steps to be applied whenever a
|
|
|
|
new comment is posted on an ``Entry``:
|
|
|
|
|
|
|
|
1. If the ``Entry``'s ``enable_comments`` field is ``False``, the
|
|
|
|
comment will simply be disallowed (i.e., immediately deleted).
|
|
|
|
|
|
|
|
2. If the ``enable_comments`` field is ``True``, the comment will be
|
|
|
|
allowed to save.
|
|
|
|
|
|
|
|
3. Once the comment is saved, an email should be sent to site staff
|
|
|
|
notifying them of the new comment.
|
|
|
|
|
|
|
|
Accomplishing this is fairly straightforward and requires very little
|
|
|
|
code::
|
|
|
|
|
|
|
|
from django.contrib.comments.moderation import CommentModerator, moderator
|
2012-09-08 15:00:04 +00:00
|
|
|
|
2009-03-23 21:22:31 +00:00
|
|
|
class EntryModerator(CommentModerator):
|
|
|
|
email_notification = True
|
|
|
|
enable_field = 'enable_comments'
|
2012-09-08 15:00:04 +00:00
|
|
|
|
2009-03-23 21:22:31 +00:00
|
|
|
moderator.register(Entry, EntryModerator)
|
|
|
|
|
|
|
|
The :class:`CommentModerator` class pre-defines a number of useful moderation
|
|
|
|
options which subclasses can enable or disable as desired, and ``moderator``
|
|
|
|
knows how to work with them to determine whether to allow a comment, whether
|
|
|
|
to moderate a comment which will be allowed to post, and whether to email
|
|
|
|
notifications of new comments.
|
|
|
|
|
|
|
|
Built-in moderation options
|
|
|
|
---------------------------
|
|
|
|
|
|
|
|
.. class:: CommentModerator
|
|
|
|
|
|
|
|
Most common comment-moderation needs can be handled by subclassing
|
|
|
|
:class:`CommentModerator` and
|
|
|
|
changing the values of pre-defined attributes; the full range of built-in
|
|
|
|
options is as follows.
|
|
|
|
|
|
|
|
.. attribute:: auto_close_field
|
|
|
|
|
|
|
|
If this is set to the name of a
|
|
|
|
:class:`~django.db.models.fields.DateField` or
|
|
|
|
:class:`~django.db.models.fields.DateTimeField` on the model for which
|
|
|
|
comments are being moderated, new comments for objects of that model
|
|
|
|
will be disallowed (immediately deleted) when a certain number of days
|
|
|
|
have passed after the date specified in that field. Must be
|
|
|
|
used in conjunction with :attr:`close_after`, which specifies the
|
|
|
|
number of days past which comments should be
|
|
|
|
disallowed. Default value is ``None``.
|
|
|
|
|
|
|
|
.. attribute:: auto_moderate_field
|
|
|
|
|
|
|
|
Like :attr:`auto_close_field`, but instead of outright deleting
|
|
|
|
new comments when the requisite number of days have elapsed,
|
|
|
|
it will simply set the ``is_public`` field of new comments to
|
|
|
|
``False`` before saving them. Must be used in conjunction with
|
|
|
|
:attr:`moderate_after`, which specifies the number of days past
|
|
|
|
which comments should be moderated. Default value is ``None``.
|
|
|
|
|
|
|
|
.. attribute:: close_after
|
|
|
|
|
|
|
|
If :attr:`auto_close_field` is used, this must specify the number
|
|
|
|
of days past the value of the field specified by
|
|
|
|
:attr:`auto_close_field` after which new comments for an object
|
2010-11-13 18:42:56 +00:00
|
|
|
should be disallowed. Allowed values are ``None``, 0 (which disallows
|
|
|
|
comments immediately), or any positive integer. Default value is
|
|
|
|
``None``.
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
.. attribute:: email_notification
|
|
|
|
|
|
|
|
If ``True``, any new comment on an object of this model which
|
|
|
|
survives moderation (i.e., is not deleted) will generate an
|
|
|
|
email to site staff. Default value is ``False``.
|
|
|
|
|
|
|
|
.. attribute:: enable_field
|
|
|
|
|
|
|
|
If this is set to the name of a
|
|
|
|
:class:`~django.db.models.fields.BooleanField` on the model
|
|
|
|
for which comments are being moderated, new comments on
|
|
|
|
objects of that model will be disallowed (immediately deleted)
|
|
|
|
whenever the value of that field is ``False`` on the object
|
|
|
|
the comment would be attached to. Default value is ``None``.
|
|
|
|
|
|
|
|
.. attribute:: moderate_after
|
|
|
|
|
|
|
|
If :attr:`auto_moderate_field` is used, this must specify the number
|
|
|
|
of days past the value of the field specified by
|
|
|
|
:attr:`auto_moderate_field` after which new comments for an object
|
2010-11-13 18:42:56 +00:00
|
|
|
should be marked non-public. Allowed values are ``None``, 0 (which
|
|
|
|
moderates comments immediately), or any positive integer. Default
|
|
|
|
value is ``None``.
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
Simply subclassing :class:`CommentModerator` and changing the values of these
|
|
|
|
options will automatically enable the various moderation methods for any
|
|
|
|
models registered using the subclass.
|
|
|
|
|
2010-11-13 18:42:56 +00:00
|
|
|
.. versionchanged:: 1.3
|
|
|
|
|
|
|
|
``moderate_after`` and ``close_after`` now accept 0 as a valid value.
|
|
|
|
|
2009-03-23 21:22:31 +00:00
|
|
|
Adding custom moderation methods
|
|
|
|
--------------------------------
|
|
|
|
|
|
|
|
For situations where the built-in options listed above are not
|
2009-05-14 15:20:50 +00:00
|
|
|
sufficient, subclasses of :class:`CommentModerator` can also override
|
|
|
|
the methods which actually perform the moderation, and apply any logic
|
|
|
|
they desire. :class:`CommentModerator` defines three methods which
|
|
|
|
determine how moderation will take place; each method will be called
|
|
|
|
by the moderation system and passed two arguments: ``comment``, which
|
|
|
|
is the new comment being posted, ``content_object``, which is the
|
|
|
|
object the comment will be attached to, and ``request``, which is the
|
2009-05-15 02:57:53 +00:00
|
|
|
:class:`~django.http.HttpRequest` in which the comment is being submitted:
|
2009-05-14 15:20:50 +00:00
|
|
|
|
|
|
|
.. method:: CommentModerator.allow(comment, content_object, request)
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
Should return ``True`` if the comment should be allowed to
|
|
|
|
post on the content object, and ``False`` otherwise (in which
|
|
|
|
case the comment will be immediately deleted).
|
|
|
|
|
2009-05-14 15:20:50 +00:00
|
|
|
.. method:: CommentModerator.email(comment, content_object, request)
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
If email notification of the new comment should be sent to
|
|
|
|
site staff or moderators, this method is responsible for
|
|
|
|
sending the email.
|
|
|
|
|
2009-05-14 15:20:50 +00:00
|
|
|
.. method:: CommentModerator.moderate(comment, content_object, request)
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
Should return ``True`` if the comment should be moderated (in
|
|
|
|
which case its ``is_public`` field will be set to ``False``
|
|
|
|
before saving), and ``False`` otherwise (in which case the
|
|
|
|
``is_public`` field will not be changed).
|
|
|
|
|
|
|
|
|
|
|
|
Registering models for moderation
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
The moderation system, represented by
|
|
|
|
``django.contrib.comments.moderation.moderator`` is an instance of the class
|
|
|
|
:class:`Moderator`, which allows registration and "unregistration" of models
|
|
|
|
via two methods:
|
|
|
|
|
|
|
|
.. function:: moderator.register(model_or_iterable, moderation_class)
|
|
|
|
|
|
|
|
Takes two arguments: the first should be either a model class
|
|
|
|
or list of model classes, and the second should be a subclass
|
|
|
|
of ``CommentModerator``, and register the model or models to
|
|
|
|
be moderated using the options defined in the
|
|
|
|
``CommentModerator`` subclass. If any of the models are
|
|
|
|
already registered for moderation, the exception
|
|
|
|
:exc:`AlreadyModerated` will be raised.
|
|
|
|
|
|
|
|
.. function:: moderator.unregister(model_or_iterable)
|
|
|
|
|
|
|
|
Takes one argument: a model class or list of model classes,
|
|
|
|
and removes the model or models from the set of models which
|
|
|
|
are being moderated. If any of the models are not currently
|
|
|
|
being moderated, the exception
|
|
|
|
:exc:`NotModerated` will be raised.
|
|
|
|
|
|
|
|
|
|
|
|
Customizing the moderation system
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
Most use cases will work easily with simple subclassing of
|
|
|
|
:class:`CommentModerator` and registration with the provided
|
|
|
|
:class:`Moderator` instance, but customization of global moderation behavior
|
|
|
|
can be achieved by subclassing :class:`Moderator` and instead registering
|
|
|
|
models with an instance of the subclass.
|
|
|
|
|
|
|
|
.. class:: Moderator
|
|
|
|
|
|
|
|
In addition to the :meth:`Moderator.register` and
|
|
|
|
:meth:`Moderator.unregister` methods detailed above, the following methods
|
|
|
|
on :class:`Moderator` can be overridden to achieve customized behavior:
|
|
|
|
|
|
|
|
.. method:: connect
|
|
|
|
|
|
|
|
Determines how moderation is set up globally. The base
|
|
|
|
implementation in
|
|
|
|
:class:`Moderator` does this by
|
2009-05-14 15:20:50 +00:00
|
|
|
attaching listeners to the :data:`~django.contrib.comments.signals.comment_will_be_posted`
|
|
|
|
and :data:`~django.contrib.comments.signals.comment_was_posted` signals from the
|
2009-03-23 21:22:31 +00:00
|
|
|
comment models.
|
|
|
|
|
2009-05-14 15:20:50 +00:00
|
|
|
.. method:: pre_save_moderation(sender, comment, request, **kwargs)
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
In the base implementation, applies all pre-save moderation
|
|
|
|
steps (such as determining whether the comment needs to be
|
|
|
|
deleted, or whether it needs to be marked as non-public or
|
|
|
|
generate an email).
|
|
|
|
|
2009-05-14 15:20:50 +00:00
|
|
|
.. method:: post_save_moderation(sender, comment, request, **kwargs)
|
2009-03-23 21:22:31 +00:00
|
|
|
|
|
|
|
In the base implementation, applies all post-save moderation
|
|
|
|
steps (currently this consists entirely of deleting comments
|
|
|
|
which were disallowed).
|