|
1 ================================== |
|
2 Customizing the comments framework |
|
3 ================================== |
|
4 |
|
5 .. currentmodule:: django.contrib.comments |
|
6 |
|
7 If the built-in comment framework doesn't quite fit your needs, you can extend |
|
8 the comment app's behavior to add custom data and logic. The comments framework |
|
9 lets you extend the built-in comment model, the built-in comment form, and the |
|
10 various comment views. |
|
11 |
|
12 The :setting:`COMMENTS_APP` setting is where this customization begins. Set |
|
13 :setting:`COMMENTS_APP` to the name of the app you'd like to use to provide |
|
14 custom behavior. You'll use the same syntax as you'd use for |
|
15 :setting:`INSTALLED_APPS`, and the app given must also be in the |
|
16 :setting:`INSTALLED_APPS` list. |
|
17 |
|
18 For example, if you wanted to use an app named ``my_comment_app``, your |
|
19 settings file would contain:: |
|
20 |
|
21 INSTALLED_APPS = [ |
|
22 ... |
|
23 'my_comment_app', |
|
24 ... |
|
25 ] |
|
26 |
|
27 COMMENTS_APP = 'my_comment_app' |
|
28 |
|
29 The app named in :setting:`COMMENTS_APP` provides its custom behavior by |
|
30 defining some module-level functions in the app's ``__init__.py``. The |
|
31 :ref:`complete list of these functions <custom-comment-app-api>` can be found |
|
32 below, but first let's look at a quick example. |
|
33 |
|
34 An example custom comments app |
|
35 ============================== |
|
36 |
|
37 One of the most common types of customization is modifying the set of fields |
|
38 provided on the built-in comment model. For example, some sites that allow |
|
39 comments want the commentator to provide a title for their comment; the built-in |
|
40 comment model has no field for that title. |
|
41 |
|
42 To make this kind of customization, we'll need to do three things: |
|
43 |
|
44 #. Create a custom comment :class:`~django.db.models.Model` that adds on the |
|
45 "title" field. |
|
46 |
|
47 #. Create a custom comment :class:`~django.forms.Form` that also adds this |
|
48 "title" field. |
|
49 |
|
50 #. Inform Django of these objects by defining a few functions in a |
|
51 custom :setting:`COMMENTS_APP`. |
|
52 |
|
53 So, carrying on the example above, we're dealing with a typical app structure in |
|
54 the ``my_custom_app`` directory:: |
|
55 |
|
56 my_custom_app/ |
|
57 __init__.py |
|
58 models.py |
|
59 forms.py |
|
60 |
|
61 In the ``models.py`` we'll define a ``CommentWithTitle`` model:: |
|
62 |
|
63 from django.db import models |
|
64 from django.contrib.comments.models import Comment |
|
65 |
|
66 class CommentWithTitle(Comment): |
|
67 title = models.CharField(max_length=300) |
|
68 |
|
69 Most custom comment models will subclass the :class:`Comment` model. However, |
|
70 if you want to substantially remove or change the fields available in the |
|
71 :class:`Comment` model, but don't want to rewrite the templates, you could |
|
72 try subclassing from :class:`BaseCommentAbstractModel`. |
|
73 |
|
74 Next, we'll define a custom comment form in ``forms.py``. This is a little more |
|
75 tricky: we have to both create a form and override |
|
76 :meth:`CommentForm.get_comment_model` and |
|
77 :meth:`CommentForm.get_comment_create_data` to return deal with our custom title |
|
78 field:: |
|
79 |
|
80 from django import forms |
|
81 from django.contrib.comments.forms import CommentForm |
|
82 from my_comment_app.models import CommentWithTitle |
|
83 |
|
84 class CommentFormWithTitle(CommentForm): |
|
85 title = forms.CharField(max_length=300) |
|
86 |
|
87 def get_comment_model(self): |
|
88 # Use our custom comment model instead of the built-in one. |
|
89 return CommentWithTitle |
|
90 |
|
91 def get_comment_create_data(self): |
|
92 # Use the data of the superclass, and add in the title field |
|
93 data = super(CommentFormWithTitle, self).get_comment_create_data() |
|
94 data['title'] = self.cleaned_data['title'] |
|
95 return data |
|
96 |
|
97 Django provides a couple of "helper" classes to make writing certain types of |
|
98 custom comment forms easier; see :mod:`django.contrib.comments.forms` for |
|
99 more. |
|
100 |
|
101 Finally, we'll define a couple of methods in ``my_custom_app/__init__.py`` to |
|
102 point Django at these classes we've created:: |
|
103 |
|
104 from my_comments_app.models import CommentWithTitle |
|
105 from my_comments_app.forms import CommentFormWithTitle |
|
106 |
|
107 def get_model(): |
|
108 return CommentWithTitle |
|
109 |
|
110 def get_form(): |
|
111 return CommentFormWithTitle |
|
112 |
|
113 |
|
114 .. warning:: |
|
115 |
|
116 Be careful not to create cyclic imports in your custom comments app. |
|
117 If you feel your comment configuration isn't being used as defined -- |
|
118 for example, if your comment moderation policy isn't being applied -- |
|
119 you may have a cyclic import problem. |
|
120 |
|
121 If you are having unexplained problems with comments behavior, check |
|
122 if your custom comments application imports (even indirectly) |
|
123 any module that itself imports Django's comments module. |
|
124 |
|
125 The above process should take care of most common situations. For more |
|
126 advanced usage, there are additional methods you can define. Those are |
|
127 explained in the next section. |
|
128 |
|
129 .. _custom-comment-app-api: |
|
130 |
|
131 Custom comment app API |
|
132 ====================== |
|
133 |
|
134 The :mod:`django.contrib.comments` app defines the following methods; any |
|
135 custom comment app must define at least one of them. All are optional, |
|
136 however. |
|
137 |
|
138 .. function:: get_model() |
|
139 |
|
140 Return the :class:`~django.db.models.Model` class to use for comments. This |
|
141 model should inherit from |
|
142 :class:`django.contrib.comments.models.BaseCommentAbstractModel`, which |
|
143 defines necessary core fields. |
|
144 |
|
145 The default implementation returns |
|
146 :class:`django.contrib.comments.models.Comment`. |
|
147 |
|
148 .. function:: get_form() |
|
149 |
|
150 Return the :class:`~django.forms.Form` class you want to use for |
|
151 creating, validating, and saving your comment model. Your custom |
|
152 comment form should accept an additional first argument, |
|
153 ``target_object``, which is the object the comment will be |
|
154 attached to. |
|
155 |
|
156 The default implementation returns |
|
157 :class:`django.contrib.comments.forms.CommentForm`. |
|
158 |
|
159 .. note:: |
|
160 |
|
161 The default comment form also includes a number of unobtrusive |
|
162 spam-prevention features (see |
|
163 :ref:`notes-on-the-comment-form`). If replacing it with your |
|
164 own form, you may want to look at the source code for the |
|
165 built-in form and consider incorporating similar features. |
|
166 |
|
167 .. function:: get_form_target() |
|
168 |
|
169 Return the URL for POSTing comments. This will be the ``<form action>`` |
|
170 attribute when rendering your comment form. |
|
171 |
|
172 The default implementation returns a reverse-resolved URL pointing |
|
173 to the :func:`post_comment` view. |
|
174 |
|
175 .. note:: |
|
176 |
|
177 If you provide a custom comment model and/or form, but you |
|
178 want to use the default :func:`post_comment` view, you will |
|
179 need to be aware that it requires the model and form to have |
|
180 certain additional attributes and methods: see the |
|
181 :func:`post_comment` view documentation for details. |
|
182 |
|
183 .. function:: get_flag_url() |
|
184 |
|
185 Return the URL for the "flag this comment" view. |
|
186 |
|
187 The default implementation returns a reverse-resolved URL pointing |
|
188 to the :func:`django.contrib.comments.views.moderation.flag` view. |
|
189 |
|
190 .. function:: get_delete_url() |
|
191 |
|
192 Return the URL for the "delete this comment" view. |
|
193 |
|
194 The default implementation returns a reverse-resolved URL pointing |
|
195 to the :func:`django.contrib.comments.views.moderation.delete` view. |
|
196 |
|
197 .. function:: get_approve_url() |
|
198 |
|
199 Return the URL for the "approve this comment from moderation" view. |
|
200 |
|
201 The default implementation returns a reverse-resolved URL pointing |
|
202 to the :func:`django.contrib.comments.views.moderation.approve` view. |