| | 1 | .. _ref-contrib-comments-custom: |
| | 2 | |
| | 3 | ================================== |
| | 4 | Customizing the comments framework |
| | 5 | ================================== |
| | 6 | |
| | 7 | Via the :setting:`COMMENTS_APP` setting, the comments framework allows |
| | 8 | you to replace the built-in comment model and comment form with your |
| | 9 | own classes. |
| | 10 | |
| | 11 | The COMMENTS_APP |
| | 12 | ================ |
| | 13 | |
| | 14 | A custom :setting:`COMMENTS_APP` should define one or more of the |
| | 15 | following module-level functions in it's ``__init__.py`` file. None of |
| | 16 | these functions are required, so you can define any combination of |
| | 17 | them (all others will use the defaults from |
| | 18 | ``django.contrib.comments``): |
| | 19 | |
| | 20 | .. function:: get_model() |
| | 21 | |
| | 22 | Return the :class:`~django.db.models.Model` class to use for |
| | 23 | comments. This model should inherit from |
| | 24 | :class:`django.contrib.comments.models.BaseCommentAbstractModel`, |
| | 25 | which defines necessary core fields. |
| | 26 | |
| | 27 | The default implementation returns |
| | 28 | :class:`django.contrib.comments.models.Comment`. |
| | 29 | |
| | 30 | .. function:: get_form() |
| | 31 | |
| | 32 | Return the :class:`~django.forms.Form` class you want to use for |
| | 33 | creating, validating, and saving your comment model. Your custom |
| | 34 | comment form should accept an additional first argument, |
| | 35 | ``target_object``, which is the object the comment will be |
| | 36 | attached to. |
| | 37 | |
| | 38 | The default implementation returns |
| | 39 | :class:`django.contrib.comments.forms.CommentForm`. |
| | 40 | |
| | 41 | .. note:: |
| | 42 | |
| | 43 | The default comment form also includes a number of unobtrusive |
| | 44 | spam-prevention features (see |
| | 45 | :ref:`notes-on-the-comment-form`). If replacing it with your |
| | 46 | own form, you may want to look at the source code for the |
| | 47 | built-in form and consider incorporating similar features. |
| | 48 | |
| | 49 | .. function:: get_form_target() |
| | 50 | |
| | 51 | Return the URL for POSTing comments. This will be the ``action`` |
| | 52 | attribute when rendering your comment form. |
| | 53 | |
| | 54 | The default implementation returns a reverse-resolved URL pointing |
| | 55 | to the :func:`post_comment` view. |
| | 56 | |
| | 57 | .. note:: |
| | 58 | |
| | 59 | If you provide a custom comment model and/or form, but you |
| | 60 | want to use the default :func:`post_comment` view, you will |
| | 61 | need to be aware that it requires the model and form to have |
| | 62 | certain additional attributes and methods: see the |
| | 63 | :func:`post_comment` view documentation for details. |
| | 64 | |
| | 65 | .. function:: get_flag_url() |
| | 66 | |
| | 67 | Return the URL for the "flag this comment" view. |
| | 68 | |
| | 69 | The default implementation returns a reverse-resolved URL pointing |
| | 70 | to the :func:`django.contrib.comments.views.moderation.flag` view. |
| | 71 | |
| | 72 | .. function:: get_delete_url() |
| | 73 | |
| | 74 | Return the URL for the "delete this comment" view. |
| | 75 | |
| | 76 | The default implementation returns a reverse-resolved URL pointing |
| | 77 | to the :func:`django.contrib.comments.views.moderation.delete` view. |
| | 78 | |
| | 79 | .. function:: get_approve_url() |
| | 80 | |
| | 81 | Return the URL for the "approve this comment from moderation" view. |
| | 82 | |
| | 83 | The default implementation returns a reverse-resolved URL pointing |
| | 84 | to the :func:`django.contrib.comments.views.moderation.approve` view. |
| | 85 | |
| | 86 | A sample custom comments app |
| | 87 | ---------------------------- |
| | 88 | |
| | 89 | A custom comments app might have an ``__init__.py`` like this:: |
| | 90 | |
| | 91 | from django.core.urlresolvers import reverse |
| | 92 | |
| | 93 | def get_model(): |
| | 94 | from my_comments_app.models import MyComment |
| | 95 | return MyComment |
| | 96 | |
| | 97 | def get_form(): |
| | 98 | from my_comments_app.forms import MyCommentForm |
| | 99 | return MyCommentForm |
| | 100 | |
| | 101 | def get_form_target(): |
| | 102 | return reverse('my_comments_app.views.post_comment') |
| | 103 | |
| | 104 | |
| | 105 | ``MyComment`` should inherit from :class:`BaseCommentAbstractModel`, |
| | 106 | so in ``models.py``:: |
| | 107 | |
| | 108 | from django.db import models |
| | 109 | from django.contrib.comments.models import BaseCommentAbstractModel |
| | 110 | |
| | 111 | class MyComment(BaseCommentAbstractModel): |
| | 112 | ... fields and custom methods ... |
| | 113 | |
| | 114 | And ``MyCommentForm`` should accept a target_object argument, |
| | 115 | so in ``forms.py``:: |
| | 116 | |
| | 117 | from django import forms |
| | 118 | |
| | 119 | class MyCommentForm(forms.Form): |
| | 120 | def __init__(self, target_object, data=None, initial=None): |
| | 121 | ... |
| | 122 | |
| | 123 | In order to enable this custom comments app, you would need to have |
| | 124 | the following in your project's ``settings.py``:: |
| | 125 | |
| | 126 | INSTALLED_APPS = ( |
| | 127 | ... |
| | 128 | 'my_comments_app', |
| | 129 | ... |
| | 130 | ) |
| | 131 | |
| | 132 | COMMENTS_APP = 'my_comments_app' |
| | 133 | |
| | 134 | |
| | 135 | API reference |
| | 136 | ================================== |
| | 137 | |
| | 138 | BaseCommentAbstractModel |
| | 139 | ------------------------ |
| | 140 | |
| | 141 | .. class:: BaseCommentAbstractModel |
| | 142 | |
| | 143 | :class:`BaseCommentAbstractModel` defines the following attributes |
| | 144 | and methods, which your custom comment model will inherit: |
| | 145 | |
| | 146 | .. attribute:: site |
| | 147 | |
| | 148 | A foreign key to the |
| | 149 | :class:`~django.contrib.sites.models.Site` model (see |
| | 150 | :ref:`ref-contrib-sites`), defining which site this comment |
| | 151 | appears on. |
| | 152 | |
| | 153 | .. attribute:: content_type |
| | 154 | |
| | 155 | A foreign key to the |
| | 156 | :class:`~django.contrib.contenttypes.models.ContentType` |
| | 157 | model. This is the content type of the target object the |
| | 158 | comment is attached to. |
| | 159 | |
| | 160 | .. attribute:: object_pk |
| | 161 | |
| | 162 | The primary key of the target object. |
| | 163 | |
| | 164 | .. attribute:: content_object |
| | 165 | |
| | 166 | A |
| | 167 | :class:`~django.contrib.contenttypes.generic.GenericForeignKey` |
| | 168 | to the target object, using the :attr:`content_type` and |
| | 169 | :attr:`object_pk` attributes. |
| | 170 | |
| | 171 | .. method:: get_content_object_url() |
| | 172 | |
| | 173 | Returns a URL that redirects to the URL of the comment's |
| | 174 | target object. |
| | 175 | |
| | 176 | post_comment view |
| | 177 | ----------------- |
| | 178 | |
| | 179 | .. function:: post_comment |
| | 180 | |
| | 181 | The default :func:`post_comment` view requires the comment model |
| | 182 | to have two additional fields: |
| | 183 | |
| | 184 | .. attribute:: user |
| | 185 | |
| | 186 | This should be a :class:`ForeignKey` to the :class:`User` |
| | 187 | model. The view will store the user who posted the comment in |
| | 188 | this field. |
| | 189 | |
| | 190 | .. attribute:: ip_address |
| | 191 | |
| | 192 | This should be an :class:`IPAddressField`. The |
| | 193 | :func:`post_comment` view will store the remote IP address of |
| | 194 | the comment poster in it. |
| | 195 | |
| | 196 | The :func:`post_comment` view also requires the comment form to |
| | 197 | have the following two methods: |
| | 198 | |
| | 199 | .. method:: security_errors() |
| | 200 | |
| | 201 | If this method returns a false value, the form will be |
| | 202 | considered to have passed anti-spam screening. If it returns |
| | 203 | any nonzero value, that value will be coerced to a string and |
| | 204 | sent as part of an HTTP 400 (bad request) response. |
| | 205 | |
| | 206 | .. method:: get_comment_object() |
| | 207 | |
| | 208 | This method will only be called if the form has passed |
| | 209 | validation and returned no :func:`security_errors()`. It |
| | 210 | should return an (unsaved) comment object, which will be |
| | 211 | annotated with the user and IP address and then saved. |