diff --git a/django/contrib/comments/forms.py b/django/contrib/comments/forms.py
index 4ba12ef..f256f5d 100644
a
|
b
|
from django import forms
|
5 | 5 | from django.forms.util import ErrorDict |
6 | 6 | from django.conf import settings |
7 | 7 | from django.contrib.contenttypes.models import ContentType |
8 | | from models import Comment |
9 | 8 | from django.utils.encoding import force_unicode |
10 | 9 | from django.utils.hashcompat import sha_constructor |
11 | 10 | from django.utils.text import get_text_list |
12 | 11 | from django.utils.translation import ungettext, ugettext_lazy as _ |
| 12 | from django.contrib.comments.models import Comment, BaseCommentAbstractModel |
13 | 13 | |
14 | 14 | COMMENT_MAX_LENGTH = getattr(settings,'COMMENT_MAX_LENGTH', 3000) |
15 | 15 | |
… |
… |
class CommentSecurityForm(forms.Form):
|
28 | 28 | initial = {} |
29 | 29 | initial.update(self.generate_security_data()) |
30 | 30 | super(CommentSecurityForm, self).__init__(data=data, initial=initial) |
31 | | |
| 31 | |
32 | 32 | def security_errors(self): |
33 | 33 | """Return just those errors associated with security""" |
34 | 34 | errors = ErrorDict() |
… |
… |
class CommentSecurityForm(forms.Form):
|
86 | 86 | info = (content_type, object_pk, timestamp, settings.SECRET_KEY) |
87 | 87 | return sha_constructor("".join(info)).hexdigest() |
88 | 88 | |
89 | | class CommentDetailsForm(CommentSecurityForm): |
| 89 | class BaseCommentAbstractForm(CommentSecurityForm): |
90 | 90 | """ |
91 | | Handles the specific details of the comment (name, comment, etc.). |
| 91 | Form for the BaseCommentAbstractModel. |
92 | 92 | """ |
93 | | name = forms.CharField(label=_("Name"), max_length=50) |
94 | | email = forms.EmailField(label=_("Email address")) |
95 | | url = forms.URLField(label=_("URL"), required=False) |
96 | | comment = forms.CharField(label=_('Comment'), widget=forms.Textarea, |
97 | | max_length=COMMENT_MAX_LENGTH) |
98 | | |
99 | 93 | def get_comment_object(self): |
100 | 94 | """ |
101 | 95 | Return a new (unsaved) comment object based on the information in this |
… |
… |
class CommentDetailsForm(CommentSecurityForm):
|
107 | 101 | """ |
108 | 102 | if not self.is_valid(): |
109 | 103 | raise ValueError("get_comment_object may only be called on valid forms") |
110 | | |
| 104 | |
111 | 105 | CommentModel = self.get_comment_model() |
112 | 106 | new = CommentModel(**self.get_comment_create_data()) |
113 | 107 | new = self.check_for_duplicate_comment(new) |
114 | | |
| 108 | |
115 | 109 | return new |
116 | | |
| 110 | |
117 | 111 | def get_comment_model(self): |
118 | 112 | """ |
119 | 113 | Get the comment model to create with this form. Subclasses in custom |
120 | 114 | comment apps should override this, get_comment_create_data, and perhaps |
121 | 115 | check_for_duplicate_comment to provide custom comment models. |
122 | 116 | """ |
123 | | return Comment |
124 | | |
| 117 | return BaseCommentAbstractModel |
| 118 | |
125 | 119 | def get_comment_create_data(self): |
126 | 120 | """ |
127 | 121 | Returns the dict of data to be used to create a comment. Subclasses in |
… |
… |
class CommentDetailsForm(CommentSecurityForm):
|
131 | 125 | return dict( |
132 | 126 | content_type = ContentType.objects.get_for_model(self.target_object), |
133 | 127 | object_pk = force_unicode(self.target_object._get_pk_val()), |
| 128 | site_id = settings.SITE_ID, |
| 129 | ) |
| 130 | |
| 131 | def check_for_duplicate_comment(self, new): |
| 132 | """ |
| 133 | This meant to be overriden in custom form. |
| 134 | Do any checks that this comment is not a duplicate here. |
| 135 | """ |
| 136 | return new |
| 137 | |
| 138 | class CommentDetailsForm(BaseCommentAbstractForm): |
| 139 | """ |
| 140 | Handles the specific details of the comment (name, comment, etc.). |
| 141 | """ |
| 142 | name = forms.CharField(label=_("Name"), max_length=50) |
| 143 | email = forms.EmailField(label=_("Email address")) |
| 144 | url = forms.URLField(label=_("URL"), required=False) |
| 145 | comment = forms.CharField(label=_('Comment'), widget=forms.Textarea, |
| 146 | max_length=COMMENT_MAX_LENGTH) |
| 147 | |
| 148 | def get_comment_model(self): |
| 149 | return Comment |
| 150 | |
| 151 | def get_comment_create_data(self): |
| 152 | data = super(CommentDetailsForm, self).get_comment_create_data() |
| 153 | data.update(dict( |
134 | 154 | user_name = self.cleaned_data["name"], |
135 | 155 | user_email = self.cleaned_data["email"], |
136 | 156 | user_url = self.cleaned_data["url"], |
137 | 157 | comment = self.cleaned_data["comment"], |
138 | 158 | submit_date = datetime.datetime.now(), |
139 | | site_id = settings.SITE_ID, |
140 | 159 | is_public = True, |
141 | 160 | is_removed = False, |
142 | | ) |
143 | | |
| 161 | )) |
| 162 | return data |
| 163 | |
144 | 164 | def check_for_duplicate_comment(self, new): |
145 | 165 | """ |
146 | 166 | Check that a submitted comment isn't a duplicate. This might be caused |
… |
… |
class CommentDetailsForm(CommentSecurityForm):
|
156 | 176 | for old in possible_duplicates: |
157 | 177 | if old.submit_date.date() == new.submit_date.date() and old.comment == new.comment: |
158 | 178 | return old |
159 | | |
| 179 | |
160 | 180 | return new |
161 | 181 | |
162 | 182 | def clean_comment(self): |
diff --git a/django/contrib/comments/models.py b/django/contrib/comments/models.py
index 56642b2..08097a0 100644
a
|
b
|
class BaseCommentAbstractModel(models.Model):
|
24 | 24 | content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk") |
25 | 25 | |
26 | 26 | # Metadata about the comment |
27 | | site = models.ForeignKey(Site) |
| 27 | site = models.ForeignKey(Site) # backward compatibility stuff |
28 | 28 | |
29 | 29 | class Meta: |
30 | 30 | abstract = True |
diff --git a/docs/ref/contrib/comments/custom.txt b/docs/ref/contrib/comments/custom.txt
index d4b1756..2952663 100644
a
|
b
|
In the ``models.py`` we'll define a ``CommentWithTitle`` model::
|
69 | 69 | title = models.CharField(max_length=300) |
70 | 70 | |
71 | 71 | All custom comment models must subclass :class:`BaseCommentAbstractModel`. |
| 72 | Or if you just want to add title field to a comment, extend :class:`Comment`. |
72 | 73 | |
73 | 74 | Next, we'll define a custom comment form in ``forms.py``. This is a little more |
74 | 75 | tricky: we have to both create a form and override |
… |
… |
tricky: we have to both create a form and override
|
77 | 78 | field:: |
78 | 79 | |
79 | 80 | from django import forms |
80 | | from django.contrib.comments.forms import CommentForm |
| 81 | from django.contrib.comments.forms import BaseCommentAbstractForm |
81 | 82 | from my_comment_app.models import CommentWithTitle |
82 | 83 | |
83 | | class CommentFormWithTitle(CommentForm): |
| 84 | class CommentFormWithTitle(BaseCommentAbstractForm): |
84 | 85 | title = forms.CharField(max_length=300) |
85 | 86 | |
86 | 87 | def get_comment_model(self): |
… |
… |
more.
|
100 | 101 | Finally, we'll define a couple of methods in ``my_custom_app/__init__.py`` to |
101 | 102 | point Django at these classes we've created:: |
102 | 103 | |
103 | | from my_comments_app.models import CommentWithTitle |
104 | | from my_comments_app.forms import CommentFormWithTitle |
| 104 | from my_comment_app.models import CommentWithTitle |
| 105 | from my_comment_app.forms import CommentFormWithTitle |
105 | 106 | |
106 | 107 | def get_model(): |
107 | 108 | return CommentWithTitle |
… |
… |
however.
|
186 | 187 | Return the URL for the "approve this comment from moderation" view. |
187 | 188 | |
188 | 189 | The default implementation returns a reverse-resolved URL pointing |
189 | | to the :func:`django.contrib.comments.views.moderation.approve` view. |
190 | | No newline at end of file |
| 190 | to the :func:`django.contrib.comments.views.moderation.approve` view. |