diff -r d0dc9aaff6af django/forms/forms.py
a
|
b
|
|
286 | 286 | self.cleaned_data = self.clean() |
287 | 287 | except ValidationError, e: |
288 | 288 | self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages) |
289 | | if self._errors: |
290 | | delattr(self, 'cleaned_data') |
291 | 289 | |
292 | 290 | def clean(self): |
293 | 291 | """ |
diff -r d0dc9aaff6af django/forms/formsets.py
a
|
b
|
|
144 | 144 | # if this is an extra form and hasn't changed, don't consider it |
145 | 145 | if i >= self.initial_form_count() and not form.has_changed(): |
146 | 146 | continue |
147 | | if form.cleaned_data[DELETION_FIELD_NAME]: |
| 147 | field = form.fields[DELETION_FIELD_NAME] |
| 148 | raw_value = form._raw_value(DELETION_FIELD_NAME) |
| 149 | should_delete = field.clean(raw_value) |
| 150 | if should_delete: |
148 | 151 | self._deleted_form_indexes.append(i) |
149 | 152 | return [self.forms[i] for i in self._deleted_form_indexes] |
150 | 153 | deleted_forms = property(_get_deleted_forms) |
… |
… |
|
231 | 234 | raw_value = form._raw_value(DELETION_FIELD_NAME) |
232 | 235 | should_delete = field.clean(raw_value) |
233 | 236 | if should_delete: |
| 237 | # clean form anyways to populate cleaned_data |
| 238 | form.full_clean() |
234 | 239 | # This form is going to be deleted so any of its errors |
235 | 240 | # should not cause the entire formset to be invalid. |
236 | 241 | continue |
diff -r d0dc9aaff6af tests/modeltests/model_forms/models.py
a
|
b
|
|
453 | 453 | >>> f.errors['slug'] |
454 | 454 | [u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."] |
455 | 455 | >>> f.cleaned_data |
456 | | Traceback (most recent call last): |
457 | | ... |
458 | | AttributeError: 'CategoryForm' object has no attribute 'cleaned_data' |
| 456 | {'url': u'foo'} |
459 | 457 | >>> f.save() |
460 | 458 | Traceback (most recent call last): |
461 | 459 | ... |
diff -r d0dc9aaff6af tests/regressiontests/forms/forms.py
a
|
b
|
|
78 | 78 | >>> p.is_valid() |
79 | 79 | False |
80 | 80 | >>> p.cleaned_data |
81 | | Traceback (most recent call last): |
82 | | ... |
83 | | AttributeError: 'Person' object has no attribute 'cleaned_data' |
| 81 | {} |
84 | 82 | >>> print p |
85 | 83 | <tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr> |
86 | 84 | <tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr> |
… |
… |
|
156 | 154 | * birthday |
157 | 155 | * This field is required. |
158 | 156 | >>> p.cleaned_data |
159 | | Traceback (most recent call last): |
160 | | ... |
161 | | AttributeError: 'Person' object has no attribute 'cleaned_data' |
| 157 | {'last_name': u'Lennon'} |
162 | 158 | >>> p['first_name'].errors |
163 | 159 | [u'This field is required.'] |
164 | 160 | >>> p['first_name'].errors.as_ul() |
… |
… |
|
1745 | 1741 | >>> form.errors |
1746 | 1742 | {'name': [u'This field is required.'], 'artist': [u'This field is required.']} |
1747 | 1743 | >>> form.cleaned_data |
1748 | | Traceback (most recent call last): |
1749 | | ... |
1750 | | AttributeError: 'SongForm' object has no attribute 'cleaned_data' |
1751 | | |
| 1744 | {} |
1752 | 1745 | |
1753 | 1746 | Now let's show what happens when empty_permitted=True and the form is empty. |
1754 | 1747 | |
… |
… |
|
1770 | 1763 | >>> form.errors |
1771 | 1764 | {'name': [u'This field is required.']} |
1772 | 1765 | >>> form.cleaned_data |
1773 | | Traceback (most recent call last): |
1774 | | ... |
1775 | | AttributeError: 'SongForm' object has no attribute 'cleaned_data' |
| 1766 | {'artist': u'The Doors'} |
1776 | 1767 | |
1777 | 1768 | If a field is not given in the data then None is returned for its data. Lets |
1778 | 1769 | make sure that when checking for empty_permitted that None is treated |
diff -r d0dc9aaff6af tests/regressiontests/forms/formsets.py
a
|
b
|
|
308 | 308 | >>> formset.is_valid() |
309 | 309 | True |
310 | 310 | |
| 311 | The formset is valid (due to short circuiting forms marked for deletion), but |
| 312 | not all forms are valid: |
| 313 | |
| 314 | >>> [form.is_valid() for form in formset.forms] |
| 315 | [True, False, True] |
| 316 | |
| 317 | But we can still access the cleaned_data attribute for each form: |
| 318 | |
| 319 | >>> [form.cleaned_data for form in formset.forms] |
| 320 | [{'field': 200, 'DELETE': False}, {'DELETE': True}, {}] |
| 321 | |
| 322 | And access the deleted form: |
| 323 | |
| 324 | >>> len(formset.deleted_forms) |
| 325 | 1 |
| 326 | >>> formset._deleted_form_indexes |
| 327 | [1] |
| 328 | |
311 | 329 | If we remove the deletion flag now we will have our validation back. |
312 | 330 | |
313 | 331 | >>> data['check-1-DELETE'] = '' |