/docs/moderation.txt
Plain Text | 286 lines | 219 code | 67 blank | 0 comment | 0 complexity | a1acb2371a211f930688066e6accd776 MD5 | raw file
1========================== 2Generic comment moderation 3========================== 4 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. 13 14 15Overview 16======== 17 18The entire system is contained within ``comment_utils.moderation``, 19and uses a two-step process to enable moderation for any given model: 20 211. A subclass of ``comment_utils.moderation.CommentModerator`` is 22 defined which specifies the moderation options the model wants to 23 enable. 24 252. The model is registered with the moderation system, passing in the 26 model class and the class which specifies its moderation options. 27 28A simple example is the best illustration of this. Suppose we have the 29following model, which would represent entries in a weblog:: 30 31 from django.db import models 32 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() 38 39Now, suppose that we want the following steps to be applied whenever a 40new comment is posted on an ``Entry``: 41 421. If the ``Entry``'s ``enable_comments`` field is ``False``, the 43 comment will simply be disallowed (i.e., immediately deleted). 44 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. 49 503. Once the comment is saved, an email should be sent to site staff 51 notifying them of the new comment. 52 53Accomplishing this is fairly straightforward and requires very little 54code:: 55 56 from comment_utils.moderation import CommentModerator, moderator 57 58 class EntryModerator(CommentModerator): 59 akismet = True 60 email_notification = True 61 enable_field = 'enable_comments' 62 63 moderator.register(Entry, EntryModerator) 64 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. 70 71 72Built-in moderation options 73--------------------------- 74 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:: 78 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``. 88 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``. 98 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``. 106 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``. 112 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``. 117 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``. 124 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``. 130 131Simply subclassing ``CommentModerator`` and changing the values of 132these options will automatically enable the various moderation methods 133for any models registered using the subclass. 134 135 136Adding custom moderation methods 137-------------------------------- 138 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:: 147 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). 152 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. 157 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). 163 164 165Built-in subclasses of ``CommentModerator`` 166------------------------------------------- 167 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 171options:: 172 173 ``AkismetModerator`` 174 Applies an Akismet spam check to all new comments for the 175 model on which it is used. 176 177 ``AlwaysModerate`` 178 Forces all new comments for its model into moderation (by 179 setting ``is_public=False``). 180 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. 185 186 187Registering models for moderation 188--------------------------------- 189 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:: 194 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. 203 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. 210 211 212Customizing the moderation system 213--------------------------------- 214 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. 220 221In addition to the ``register`` and ``unregister`` methods detailed 222above, the following methods on ``Moderator`` can be overridden to 223achieve customized behavior:: 224 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. 230 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). 236 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). 241 242 243Automatically deleting non-public comments 244------------------------------------------ 245 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/delete_spam_comments.py`` -- 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. 251 252**Required arguments** 253 254``-s``, ``--settings`` 255 Specifies the Django settings module to use. 256 257 258**Optional arguments** 259 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. 265 266``-d``, ``--dry-run`` 267 Prints the number of comments which would have been deleted, but 268 does not actually delete them. 269 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. 274 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. 280 281So, for example, the script could be used like so:: 282 283 ``python /path/to/comment_utils/bin/delete_spam_comments.py --settings=mysite.settings --age=7 --type=registered 284 285This would delete every non-public ``Comment`` in the ``mysite`` 286database older than 7 days.