mirror of
https://github.com/django/django.git
synced 2024-12-27 11:35:53 +00:00
218 lines
7.4 KiB
Plaintext
218 lines
7.4 KiB
Plaintext
.. highlightlang:: html+django
|
|
|
|
===========================================
|
|
Example of using the built-in comments app
|
|
===========================================
|
|
|
|
.. warning::
|
|
|
|
Django's comment framework has been deprecated and is no longer supported.
|
|
Most users will be better served with a custom solution, or a hosted
|
|
product like Disqus__.
|
|
|
|
The code formerly known as ``django.contrib.comments`` is `still available
|
|
in an external repository`__.
|
|
|
|
__ https://disqus.com/
|
|
__ https://github.com/django/django-contrib-comments
|
|
|
|
Follow the first three steps of the quick start guide in the
|
|
:doc:`documentation </ref/contrib/comments/index>`.
|
|
|
|
Now suppose, you have an app (``blog``) with a model (``Post``)
|
|
to which you want to attach comments. Let's also suppose that
|
|
you have a template called ``blog_detail.html`` where you want
|
|
to display the comments list and comment form.
|
|
|
|
Template
|
|
========
|
|
|
|
First, we should load the ``comment`` template tags in the
|
|
``blog_detail.html`` so that we can use its functionality. So
|
|
just like all other custom template tag libraries::
|
|
|
|
{% load comments %}
|
|
|
|
Next, let's add the number of comments attached to the particular
|
|
model instance of ``Post``. For this we assume that a context
|
|
variable ``object_pk`` is present which gives the ``id`` of the
|
|
instance of ``Post``.
|
|
|
|
The usage of the :ttag:`get_comment_count` tag is like below::
|
|
|
|
{% get_comment_count for blog.post object_pk as comment_count %}
|
|
<p>{{ comment_count }} comments have been posted.</p>
|
|
|
|
If you have the instance (say ``entry``) of the model (``Post``)
|
|
available in the context, then you can refer to it directly::
|
|
|
|
{% get_comment_count for entry as comment_count %}
|
|
<p>{{ comment_count }} comments have been posted.</p>
|
|
|
|
Next, we can use the :ttag:`render_comment_list` tag, to render all comments
|
|
to the given instance (``entry``) by using the ``comments/list.html`` template::
|
|
|
|
{% render_comment_list for entry %}
|
|
|
|
Django will will look for the ``list.html`` under the following directories
|
|
(for our example)::
|
|
|
|
comments/blog/post/list.html
|
|
comments/blog/list.html
|
|
comments/list.html
|
|
|
|
To get a list of comments, we make use of the :ttag:`get_comment_list` tag.
|
|
Using this tag is very similar to the :ttag:`get_comment_count` tag. We
|
|
need to remember that :ttag:`get_comment_list` returns a list of comments
|
|
and hence we have to iterate through them to display them::
|
|
|
|
{% get_comment_list for blog.post object_pk as comment_list %}
|
|
{% for comment in comment_list %}
|
|
<p>Posted by: {{ comment.user_name }} on {{ comment.submit_date }}</p>
|
|
...
|
|
<p>Comment: {{ comment.comment }}</p>
|
|
...
|
|
{% endfor %}
|
|
|
|
Finally, we display the comment form, enabling users to enter their
|
|
comments. There are two ways of doing so. The first is when you want to
|
|
display the comments template available under your ``comments/form.html``.
|
|
The other method gives you a chance to customize the form.
|
|
|
|
The first method makes use of the :ttag:`render_comment_form` tag. Its usage
|
|
too is similar to the other three tags we have discussed above::
|
|
|
|
{% render_comment_form for entry %}
|
|
|
|
It looks for the ``form.html`` under the following directories
|
|
(for our example)::
|
|
|
|
comments/blog/post/form.html
|
|
comments/blog/form.html
|
|
comments/form.html
|
|
|
|
Since we customize the form in the second method, we make use of another
|
|
tag called :ttag:`comment_form_target`. This tag on rendering gives the URL
|
|
where the comment form is posted. Without any :doc:`customization
|
|
</ref/contrib/comments/custom>`, :ttag:`comment_form_target` evaluates to
|
|
``/comments/post/``. We use this tag in the form's ``action`` attribute.
|
|
|
|
The :ttag:`get_comment_form` tag renders a ``form`` for a model instance by
|
|
creating a context variable. One can iterate over the ``form`` object to
|
|
get individual fields. This gives you fine-grain control over the form::
|
|
|
|
{% for field in form %}
|
|
{% ifequal field.name "comment" %}
|
|
<!-- Customize the "comment" field, say, make CSS changes -->
|
|
...
|
|
{% endfor %}
|
|
|
|
But let's look at a simple example::
|
|
|
|
{% get_comment_form for entry as form %}
|
|
<!-- A context variable called form is created with the necessary hidden
|
|
fields, timestamps and security hashes -->
|
|
<table>
|
|
<form action="{% comment_form_target %}" method="post">
|
|
{% csrf_token %}
|
|
{{ form }}
|
|
<tr>
|
|
<td colspan="2">
|
|
<input type="submit" name="submit" value="Post">
|
|
<input type="submit" name="preview" value="Preview">
|
|
</td>
|
|
</tr>
|
|
</form>
|
|
</table>
|
|
|
|
Flagging
|
|
========
|
|
|
|
If you want your users to be able to flag comments (say for profanity), you
|
|
can just direct them (by placing a link in your comment list) to ``/flag/{{
|
|
comment.id }}/``. Similarly, a user with requisite permissions (``"Can
|
|
moderate comments"``) can approve and delete comments. This can also be
|
|
done through the ``admin`` as you'll see later. You might also want to
|
|
customize the following templates:
|
|
|
|
* ``flag.html``
|
|
* ``flagged.html``
|
|
* ``approve.html``
|
|
* ``approved.html``
|
|
* ``delete.html``
|
|
* ``deleted.html``
|
|
|
|
found under the directory structure we saw for ``form.html``.
|
|
|
|
Feeds
|
|
=====
|
|
|
|
Suppose you want to export a :doc:`feed </ref/contrib/syndication>` of the
|
|
latest comments, you can use the built-in ``LatestCommentFeed``. Just
|
|
enable it in your project's ``urls.py``:
|
|
|
|
.. code-block:: python
|
|
|
|
from django.conf.urls import patterns
|
|
from django.contrib.comments.feeds import LatestCommentFeed
|
|
|
|
urlpatterns = patterns('',
|
|
# ...
|
|
(r'^feeds/latest/$', LatestCommentFeed()),
|
|
# ...
|
|
)
|
|
|
|
Now you should have the latest comment feeds being served off ``/feeds/latest/``.
|
|
|
|
|
|
Moderation
|
|
==========
|
|
|
|
Now that we have the comments framework working, we might want to have some
|
|
moderation setup to administer the comments. The comments framework comes
|
|
built-in with :doc:`generic comment moderation
|
|
</ref/contrib/comments/moderation>`. The comment moderation has the following
|
|
features (all of which or only certain can be enabled):
|
|
|
|
* Enable comments for a particular model instance.
|
|
* Close comments after a particular (user-defined) number of days.
|
|
* Email new comments to the site-staff.
|
|
|
|
To enable comment moderation, we subclass the ``CommentModerator`` and
|
|
register it with the moderation features we want. Let's suppose we want to
|
|
close comments after 7 days of posting and also send out an email to the
|
|
site staff. In ``blog/models.py``, we register a comment moderator in the
|
|
following way:
|
|
|
|
.. code-block:: python
|
|
|
|
from django.contrib.comments.moderation import CommentModerator, moderator
|
|
from django.db import models
|
|
|
|
class Post(models.Model):
|
|
title = models.CharField(max_length = 255)
|
|
content = models.TextField()
|
|
posted_date = models.DateTimeField()
|
|
|
|
class PostModerator(CommentModerator):
|
|
email_notification = True
|
|
auto_close_field = 'posted_date'
|
|
# Close the comments after 7 days.
|
|
close_after = 7
|
|
|
|
moderator.register(Post, PostModerator)
|
|
|
|
The generic comment moderation also has the facility to remove comments.
|
|
These comments can then be moderated by any user who has access to the
|
|
``admin`` site and the ``Can moderate comments`` permission (can be set
|
|
under the ``Users`` page in the ``admin``).
|
|
|
|
The moderator can ``Flag``, ``Approve`` or ``Remove`` comments using the
|
|
``Action`` drop-down in the ``admin`` under the ``Comments`` page.
|
|
|
|
.. note::
|
|
|
|
Only a super-user will be able to delete comments from the database.
|
|
``Remove Comments`` only sets the ``is_public`` attribute to
|
|
``False``.
|