diff options
| author | Andrew Godwin <andrew@aeracode.org> | 2013-05-19 03:56:14 -0700 |
|---|---|---|
| committer | Andrew Godwin <andrew@aeracode.org> | 2013-05-19 03:56:14 -0700 |
| commit | 04e0fc029f6868221dbba850e5a8830c8d11c42c (patch) | |
| tree | 1f3eeeb4ea46b44e60c92000b3dcbf9be5e22dba | |
| parent | 7a99d1e167f81c5fcd1b9f7f548c5d6959cef2ef (diff) | |
| parent | b11b036145d6a1e9d2192e332c8a221a595be1b6 (diff) | |
Merge pull request #1094 from senko/ticket_11160
Fixed #11160: Formset non_form_errors returns ErrorList() if is_valid is not called
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/forms/formsets.py | 11 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_formsets.py | 14 |
3 files changed, 22 insertions, 4 deletions
@@ -474,6 +474,7 @@ answer newbie questions, and generally made Django that much better: Luciano Ramalho Amit Ramon <amit.ramon@gmail.com> Philippe Raoult <philippe.raoult@n2nsoft.com> + Senko Rašić <senko.rasic@dobarkod.hr> Massimiliano Ravelli <massimiliano.ravelli@gmail.com> Brian Ray <http://brianray.chipy.org/> Lee Reilly <lee@leereilly.net> diff --git a/django/forms/formsets.py b/django/forms/formsets.py index d421770093..3ec94d20ec 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -250,9 +250,9 @@ class BaseFormSet(object): form -- i.e., from formset.clean(). Returns an empty ErrorList if there are none. """ - if self._non_form_errors is not None: - return self._non_form_errors - return self.error_class() + if self._non_form_errors is None: + self.full_clean() + return self._non_form_errors @property def errors(self): @@ -291,9 +291,12 @@ class BaseFormSet(object): def full_clean(self): """ - Cleans all of self.data and populates self._errors. + Cleans all of self.data and populates self._errors and + self._non_form_errors. """ self._errors = [] + self._non_form_errors = self.error_class() + if not self.is_bound: # Stop further processing. return for i in range(0, self.total_form_count()): diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py index 4ac3c5ecf1..31adb921ba 100644 --- a/tests/forms_tests/tests/test_formsets.py +++ b/tests/forms_tests/tests/test_formsets.py @@ -972,6 +972,20 @@ class FormsFormsetTestCase(TestCase): finally: formsets.DEFAULT_MAX_NUM = _old_DEFAULT_MAX_NUM + def test_non_form_errors_run_full_clean(self): + # Regression test for #11160 + # If non_form_errors() is called without calling is_valid() first, + # it should ensure that full_clean() is called. + class BaseCustomFormSet(BaseFormSet): + def clean(self): + raise ValidationError("This is a non-form error") + + ChoiceFormSet = formset_factory(Choice, formset=BaseCustomFormSet) + formset = ChoiceFormSet(data, auto_id=False, prefix='choices') + self.assertTrue(isinstance(formset.non_form_errors(), ErrorList)) + self.assertEqual(list(formset.non_form_errors()), + ['This is a non-form error']) + data = { 'choices-TOTAL_FORMS': '1', # the number of forms rendered |
