PageRenderTime 38ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

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