370 lines
12 KiB
Plaintext
370 lines
12 KiB
Plaintext
===========================
|
|
Django's comments framework
|
|
===========================
|
|
|
|
.. module:: django.contrib.comments
|
|
:synopsis: Django's comment framework
|
|
|
|
.. highlightlang:: html+django
|
|
|
|
.. 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
|
|
|
|
Django includes a simple, yet customizable comments framework. The built-in
|
|
comments framework can be used to attach comments to any model, so you can use
|
|
it for comments on blog entries, photos, book chapters, or anything else.
|
|
|
|
Quick start guide
|
|
=================
|
|
|
|
To get started using the ``comments`` app, follow these steps:
|
|
|
|
#. Install the comments framework by adding ``'django.contrib.comments'`` to
|
|
:setting:`INSTALLED_APPS`.
|
|
|
|
#. Run ``manage.py migrate`` so that Django will create the comment tables.
|
|
|
|
#. Add the comment app's URLs to your project's ``urls.py``:
|
|
|
|
.. code-block:: python
|
|
|
|
urlpatterns = patterns('',
|
|
...
|
|
(r'^comments/', include('django.contrib.comments.urls')),
|
|
...
|
|
)
|
|
|
|
#. Use the `comment template tags`_ below to embed comments in your
|
|
templates.
|
|
|
|
You might also want to examine :ref:`the available settings
|
|
<settings-comments>`.
|
|
|
|
Comment template tags
|
|
=====================
|
|
|
|
You'll primarily interact with the comment system through a series of template
|
|
tags that let you embed comments and generate forms for your users to post them.
|
|
|
|
Like all custom template tag libraries, you'll need to :ref:`load the custom
|
|
tags <loading-custom-template-libraries>` before you can use them::
|
|
|
|
{% load comments %}
|
|
|
|
Once loaded you can use the template tags below.
|
|
|
|
Specifying which object comments are attached to
|
|
------------------------------------------------
|
|
|
|
Django's comments are all "attached" to some parent object. This can be any
|
|
instance of a Django model. Each of the tags below gives you a couple of
|
|
different ways you can specify which object to attach to:
|
|
|
|
#. Refer to the object directly -- the more common method. Most of the
|
|
time, you'll have some object in the template's context you want
|
|
to attach the comment to; you can simply use that object.
|
|
|
|
For example, in a blog entry page that has a variable named ``entry``,
|
|
you could use the following to load the number of comments::
|
|
|
|
{% get_comment_count for entry as comment_count %}.
|
|
|
|
#. Refer to the object by content-type and object id. You'd use this method
|
|
if you, for some reason, don't actually have direct access to the object.
|
|
|
|
Following the above example, if you knew the object ID was ``14`` but
|
|
didn't have access to the actual object, you could do something like::
|
|
|
|
{% get_comment_count for blog.entry 14 as comment_count %}
|
|
|
|
In the above, ``blog.entry`` is the app label and (lower-cased) model
|
|
name of the model class.
|
|
|
|
Displaying comments
|
|
-------------------
|
|
|
|
To display a list of comments, you can use the template tags
|
|
:ttag:`render_comment_list` or :ttag:`get_comment_list`.
|
|
|
|
.. templatetag:: render_comment_list
|
|
|
|
Quickly rendering a comment list
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The easiest way to display a list of comments for some object is by using
|
|
:ttag:`render_comment_list`::
|
|
|
|
{% render_comment_list for [object] %}
|
|
|
|
For example::
|
|
|
|
{% render_comment_list for event %}
|
|
|
|
This will render comments using a template named ``comments/list.html``, a
|
|
default version of which is included with Django.
|
|
|
|
.. templatetag:: get_comment_list
|
|
|
|
Rendering a custom comment list
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
To get the list of comments for some object, use :ttag:`get_comment_list`::
|
|
|
|
{% get_comment_list for [object] as [varname] %}
|
|
|
|
For example::
|
|
|
|
{% get_comment_list for event as comment_list %}
|
|
{% for comment in comment_list %}
|
|
...
|
|
{% endfor %}
|
|
|
|
This returns a list of :class:`~django.contrib.comments.models.Comment` objects;
|
|
see :doc:`the comment model documentation </ref/contrib/comments/models>` for
|
|
details.
|
|
|
|
.. templatetag:: get_comment_permalink
|
|
|
|
Linking to comments
|
|
-------------------
|
|
|
|
To provide a permalink to a specific comment, use :ttag:`get_comment_permalink`::
|
|
|
|
{% get_comment_permalink comment_obj [format_string] %}
|
|
|
|
By default, the named anchor that will be appended to the URL will be the letter
|
|
'c' followed by the comment id, for example 'c82'. You may specify a custom
|
|
format string if you wish to override this behavior::
|
|
|
|
{% get_comment_permalink comment "#c%(id)s-by-%(user_name)s"%}
|
|
|
|
The format string is a standard python format string. Valid mapping keys
|
|
include any attributes of the comment object.
|
|
|
|
Regardless of whether you specify a custom anchor pattern, you must supply a
|
|
matching named anchor at a suitable place in your template.
|
|
|
|
For example::
|
|
|
|
{% for comment in comment_list %}
|
|
<a name="c{{ comment.id }}"></a>
|
|
<a href="{% get_comment_permalink comment %}">
|
|
permalink for comment #{{ forloop.counter }}
|
|
</a>
|
|
...
|
|
{% endfor %}
|
|
|
|
.. warning::
|
|
|
|
There's a `known bug`_ in Safari/Webkit which causes the named anchor to be
|
|
forgotten following a redirect. The practical impact for comments is that
|
|
the Safari/webkit browsers will arrive at the correct page but will not
|
|
scroll to the named anchor.
|
|
|
|
.. _`known bug`: https://bugs.webkit.org/show_bug.cgi?id=24175
|
|
|
|
.. templatetag:: get_comment_count
|
|
|
|
Counting comments
|
|
-----------------
|
|
|
|
To count comments attached to an object, use :ttag:`get_comment_count`::
|
|
|
|
{% get_comment_count for [object] as [varname] %}
|
|
|
|
For example::
|
|
|
|
{% get_comment_count for event as comment_count %}
|
|
|
|
<p>This event has {{ comment_count }} comments.</p>
|
|
|
|
|
|
Displaying the comment post form
|
|
--------------------------------
|
|
|
|
To show the form that users will use to post a comment, you can use
|
|
:ttag:`render_comment_form` or :ttag:`get_comment_form`
|
|
|
|
.. templatetag:: render_comment_form
|
|
|
|
Quickly rendering the comment form
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The easiest way to display a comment form is by using
|
|
:ttag:`render_comment_form`::
|
|
|
|
{% render_comment_form for [object] %}
|
|
|
|
For example::
|
|
|
|
{% render_comment_form for event %}
|
|
|
|
This will render comments using a template named ``comments/form.html``, a
|
|
default version of which is included with Django.
|
|
|
|
.. templatetag:: get_comment_form
|
|
|
|
Rendering a custom comment form
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If you want more control over the look and feel of the comment form, you may use
|
|
:ttag:`get_comment_form` to get a :doc:`form object </topics/forms/index>` that
|
|
you can use in the template::
|
|
|
|
{% get_comment_form for [object] as [varname] %}
|
|
|
|
A complete form might look like::
|
|
|
|
{% get_comment_form for event as form %}
|
|
<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>
|
|
|
|
Be sure to read the `notes on the comment form`_, below, for some special
|
|
considerations you'll need to make if you're using this approach.
|
|
|
|
.. templatetag:: comment_form_target
|
|
|
|
Getting the comment form target
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
You may have noticed that the above example uses another template tag --
|
|
:ttag:`comment_form_target` -- to actually get the ``action`` attribute of the
|
|
form. This will always return the correct URL that comments should be posted to;
|
|
you'll always want to use it like above::
|
|
|
|
<form action="{% comment_form_target %}" method="post">
|
|
|
|
Redirecting after the comment post
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
To specify the URL you want to redirect to after the comment has been posted,
|
|
you can include a hidden form input called ``next`` in your comment form. For example::
|
|
|
|
<input type="hidden" name="next" value="{% url 'my_comment_was_posted' %}" />
|
|
|
|
Providing a comment form for authenticated users
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If a user is already authenticated, it makes little sense to display the name,
|
|
email, and URL fields, since these can already be retrieved from their login
|
|
data and profile. In addition, some sites will only accept comments from
|
|
authenticated users.
|
|
|
|
To provide a comment form for authenticated users, you can manually provide the
|
|
additional fields expected by the Django comments framework. For example,
|
|
assuming comments are attached to the model "object"::
|
|
|
|
{% if user.is_authenticated %}
|
|
{% get_comment_form for object as form %}
|
|
<form action="{% comment_form_target %}" method="POST">
|
|
{% csrf_token %}
|
|
{{ form.comment }}
|
|
{{ form.honeypot }}
|
|
{{ form.content_type }}
|
|
{{ form.object_pk }}
|
|
{{ form.timestamp }}
|
|
{{ form.security_hash }}
|
|
<input type="hidden" name="next" value="{% url 'object_detail_view' object.id %}" />
|
|
<input type="submit" value="Add comment" id="id_submit" />
|
|
</form>
|
|
{% else %}
|
|
<p>Please <a href="{% url 'auth_login' %}">log in</a> to leave a comment.</p>
|
|
{% endif %}
|
|
|
|
The honeypot, content_type, object_pk, timestamp, and security_hash fields are
|
|
fields that would have been created automatically if you had simply used
|
|
``{{ form }}`` in your template, and are referred to in `Notes on the comment
|
|
form`_ below.
|
|
|
|
Note that we do not need to specify the user to be associated with comments
|
|
submitted by authenticated users. This is possible because the :doc:`Built-in
|
|
Comment Models</ref/contrib/comments/models>` that come with Django associate
|
|
comments with authenticated users by default.
|
|
|
|
In this example, the honeypot field will still be visible to the user; you'll
|
|
need to hide that field in your CSS::
|
|
|
|
#id_honeypot {
|
|
display: none;
|
|
}
|
|
|
|
If you want to accept either anonymous or authenticated comments, replace the
|
|
contents of the "else" clause above with a standard comment form and the right
|
|
thing will happen whether a user is logged in or not.
|
|
|
|
.. _notes-on-the-comment-form:
|
|
|
|
Notes on the comment form
|
|
-------------------------
|
|
|
|
The form used by the comment system has a few important anti-spam attributes you
|
|
should know about:
|
|
|
|
* It contains a number of hidden fields that contain timestamps, information
|
|
about the object the comment should be attached to, and a "security hash"
|
|
used to validate this information. If someone tampers with this data --
|
|
something comment spammers will try -- the comment submission will fail.
|
|
|
|
If you're rendering a custom comment form, you'll need to make sure to
|
|
pass these values through unchanged.
|
|
|
|
* The timestamp is used to ensure that "reply attacks" can't continue very
|
|
long. Users who wait too long between requesting the form and posting a
|
|
comment will have their submissions refused.
|
|
|
|
* The comment form includes a "honeypot_" field. It's a trap: if any data is
|
|
entered in that field, the comment will be considered spam (spammers often
|
|
automatically fill in all fields in an attempt to make valid submissions).
|
|
|
|
The default form hides this field with a piece of CSS and further labels
|
|
it with a warning field; if you use the comment form with a custom
|
|
template you should be sure to do the same.
|
|
|
|
The comments app also depends on the more general :doc:`Cross Site Request
|
|
Forgery protection </ref/contrib/csrf>` that comes with Django. As described in
|
|
the documentation, it is best to use ``CsrfViewMiddleware``. However, if you
|
|
are not using that, you will need to use the ``csrf_protect`` decorator on any
|
|
views that include the comment form, in order for those views to be able to
|
|
output the CSRF token and cookie.
|
|
|
|
.. _honeypot: http://en.wikipedia.org/wiki/Honeypot_(computing)
|
|
|
|
|
|
Configuration
|
|
=============
|
|
|
|
See :ref:`comment settings <settings-comments>`.
|
|
|
|
|
|
More information
|
|
================
|
|
|
|
.. toctree::
|
|
:maxdepth: 1
|
|
|
|
models
|
|
signals
|
|
custom
|
|
forms
|
|
moderation
|
|
example
|