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