mirror of
				https://github.com/django/django.git
				synced 2025-11-03 21:25:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			357 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			357 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
===========================
 | 
						|
Django's comments framework
 | 
						|
===========================
 | 
						|
 | 
						|
.. module:: django.contrib.comments
 | 
						|
   :synopsis: Django's comment framework
 | 
						|
 | 
						|
.. highlightlang:: html+django
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
.. note::
 | 
						|
 | 
						|
    If you used to use Django's older (undocumented) comments framework, you'll
 | 
						|
    need to upgrade. See the :doc:`upgrade guide </ref/contrib/comments/upgrade>`
 | 
						|
    for instructions.
 | 
						|
 | 
						|
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 syncdb`` 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 :doc:`/ref/contrib/comments/settings`.
 | 
						|
 | 
						|
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 use 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)
 | 
						|
 | 
						|
More information
 | 
						|
================
 | 
						|
 | 
						|
.. toctree::
 | 
						|
   :maxdepth: 1
 | 
						|
 | 
						|
   models
 | 
						|
   settings
 | 
						|
   signals
 | 
						|
   upgrade
 | 
						|
   custom
 | 
						|
   forms
 | 
						|
   moderation
 | 
						|
   example
 |