example.txt 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. .. highlightlang:: html+django
  2. ===========================================
  3. Example of using the in-built comments app
  4. ===========================================
  5. Follow the first three steps of the quick start guide in the
  6. :doc:`documentation </ref/contrib/comments/index>`.
  7. Now suppose, you have an app (``blog``) with a model (``Post``)
  8. to which you want to attach comments. Let us also suppose that
  9. you have a template called ``blog_detail.html`` where you want
  10. to display the comments list and comment form.
  11. Template
  12. ========
  13. First, we should load the ``comment`` template tags in the
  14. ``blog_detail.html`` so that we can use it's functionality. So
  15. just like all other custom template tag libraries::
  16. {% load comments %}
  17. Next, let us add the number of comments attached to the particular
  18. model instance of ``Post``. For this we assume that a context
  19. variable ``object_pk`` is present which gives the ``id`` of the
  20. instance of ``Post``.
  21. The usage of the :ttag:`get_comment_count` tag is like below::
  22. {% get_comment_count for blog.post object_pk as comment_count %}
  23. <p>{{ comment_count }} comments have been posted.</p>
  24. If you have the instance (say ``entry``) of the model (``Post``)
  25. available in the context, then you can refer to it directly::
  26. {% get_comment_count for entry as comment_count %}
  27. <p>{{ comment_count }} comments have been posted.</p>
  28. .. versionadded:: 1.2
  29. Next, we can use the :ttag:`render_comment_list` tag, to render all comments
  30. to the given instance (``entry``) by using the ``comments/list.html`` template.
  31. {% render_comment_list for entry %}
  32. Django will will look for the ``list.html`` under the following directories
  33. (for our example)::
  34. comments/blog/post/list.html
  35. comments/blog/list.html
  36. comments/list.html
  37. To get a list of comments, we make use of the :ttag:`get_comment_list` tag.
  38. This tag's usage is very similar to the :ttag:`get_comment_count` tag. We
  39. need to remember that the :ttag:`get_comment_list` returns a list of comments
  40. and hence we will have to iterate through them to display them::
  41. {% get_comment_list for blog.post object_pk as comment_list %}
  42. {% for comment in comment_list %}
  43. <p>Posted by: {{ comment.user_name }} on {{ comment.submit_date }}</p>
  44. ...
  45. <p>Comment: {{ comment.comment }}</p>
  46. ...
  47. {% endfor %}
  48. Finally, we display the comment form, enabling users to enter their
  49. comments. There are two ways of doing so. The first is when you want to
  50. display the comments template available under your ``comments/form.html``.
  51. The other method gives you a chance to customize the form.
  52. The first method makes use of the :ttag:`render_comment_form` tag. It's usage
  53. too is similar to the other three tags we have discussed above::
  54. {% render_comment_form for entry %}
  55. It looks for the ``form.html`` under the following directories
  56. (for our example)::
  57. comments/blog/post/form.html
  58. comments/blog/form.html
  59. comments/form.html
  60. Since we customize the form in the second method, we make use of another
  61. tag called :ttag:`comment_form_target`. This tag on rendering gives the URL
  62. where the comment form is posted. Without any :doc:`customization
  63. </ref/contrib/comments/custom>`, :ttag:`comment_form_target` evaluates to
  64. ``/comments/post/``. We use this tag in the form's ``action`` attribute.
  65. The :ttag:`get_comment_form` tag renders a ``form`` for a model instance by
  66. creating a context variable. One can iterate over the ``form`` object to
  67. get individual fields. This gives you fine-grain control over the form::
  68. {% for field in form %}
  69. {% ifequal field.name "comment" %}
  70. <!-- Customize the "comment" field, say, make CSS changes -->
  71. ...
  72. {% endfor %}
  73. But let's look at a simple example::
  74. {% get_comment_form for entry as form %}
  75. <!-- A context variable called form is created with the necessary hidden
  76. fields, timestamps and security hashes -->
  77. <table>
  78. <form action="{% comment_form_target %}" method="post">
  79. {% csrf_token %}
  80. {{ form }}
  81. <tr>
  82. <td colspan="2">
  83. <input type="submit" name="submit" value="Post">
  84. <input type="submit" name="preview" value="Preview">
  85. </td>
  86. </tr>
  87. </form>
  88. </table>
  89. Flagging
  90. ========
  91. If you want your users to be able to flag comments (say for profanity), you
  92. can just direct them (by placing a link in your comment list) to ``/flag/{{
  93. comment.id }}/``. Similarly, a user with requisite permissions (``"Can
  94. moderate comments"``) can approve and delete comments. This can also be
  95. done through the ``admin`` as you'll see later. You might also want to
  96. customize the following templates:
  97. * ``flag.html``
  98. * ``flagged.html``
  99. * ``approve.html``
  100. * ``approved.html``
  101. * ``delete.html``
  102. * ``deleted.html``
  103. found under the directory structure we saw for ``form.html``.
  104. Feeds
  105. =====
  106. Suppose you want to export a :doc:`feed </ref/contrib/syndication>` of the
  107. latest comments, you can use the in-built :class:`LatestCommentFeed`. Just
  108. enable it in your project's ``urls.py``:
  109. .. code-block:: python
  110. from django.conf.urls import patterns, url, include
  111. from django.contrib.comments.feeds import LatestCommentFeed
  112. urlpatterns = patterns('',
  113. # ...
  114. (r'^feeds/latest/$', LatestCommentFeed()),
  115. # ...
  116. )
  117. Now you should have the latest comment feeds being served off ``/feeds/latest/``.
  118. .. versionchanged:: 1.3
  119. Prior to Django 1.3, the LatestCommentFeed was deployed using the
  120. syndication feed view:
  121. .. code-block:: python
  122. from django.conf.urls import patterns
  123. from django.contrib.comments.feeds import LatestCommentFeed
  124. feeds = {
  125. 'latest': LatestCommentFeed,
  126. }
  127. urlpatterns = patterns('',
  128. # ...
  129. (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
  130. {'feed_dict': feeds}),
  131. # ...
  132. )
  133. Moderation
  134. ==========
  135. Now that we have the comments framework working, we might want to have some
  136. moderation setup to administer the comments. The comments framework comes
  137. in-built with :doc:`generic comment moderation
  138. </ref/contrib/comments/moderation>`. The comment moderation has the following
  139. features (all of which or only certain can be enabled):
  140. * Enable comments for a particular model instance.
  141. * Close comments after a particular (user-defined) number of days.
  142. * Email new comments to the site-staff.
  143. To enable comment moderation, we subclass the :class:`CommentModerator` and
  144. register it with the moderation features we want. Let us suppose we want to
  145. close comments after 7 days of posting and also send out an email to the
  146. site staff. In ``blog/models.py``, we register a comment moderator in the
  147. following way:
  148. .. code-block:: python
  149. from django.contrib.comments.moderation import CommentModerator, moderator
  150. from django.db import models
  151. class Post(models.Model):
  152. title = models.CharField(max_length = 255)
  153. content = models.TextField()
  154. posted_date = models.DateTimeField()
  155. class PostModerator(CommentModerator):
  156. email_notification = True
  157. auto_close_field = 'posted_date'
  158. # Close the comments after 7 days.
  159. close_after = 7
  160. moderator.register(Post, PostModerator)
  161. The generic comment moderation also has the facility to remove comments.
  162. These comments can then be moderated by any user who has access to the
  163. ``admin`` site and the ``Can moderate comments`` permission (can be set
  164. under the ``Users`` page in the ``admin``).
  165. The moderator can ``Flag``, ``Approve`` or ``Remove`` comments using the
  166. ``Action`` drop-down in the ``admin`` under the ``Comments`` page.
  167. .. note::
  168. Only a super-user will be able to delete comments from the database.
  169. ``Remove Comments`` only sets the ``is_public`` attribute to
  170. ``False``.