diff options
| author | Ties Jan Hefting <hello@tiesjan.com> | 2021-07-07 22:50:30 +0200 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2021-07-15 07:00:39 +0200 |
| commit | 84400d2e9db7c51fee4e9bb04c028f665b8e7624 (patch) | |
| tree | 467414be65e1641a02dbcafa575acfff3b09c2b2 | |
| parent | 7f33c1e22dbc34a7afae7967783725b10f1f13b1 (diff) | |
Fixed #32905 -- Added CSS class for non-form errors of formsets.
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/forms/formsets.py | 7 | ||||
| -rw-r--r-- | docs/releases/4.0.txt | 4 | ||||
| -rw-r--r-- | docs/topics/forms/formsets.txt | 14 | ||||
| -rw-r--r-- | tests/admin_views/tests.py | 5 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_formsets.py | 14 |
6 files changed, 42 insertions, 3 deletions
@@ -906,6 +906,7 @@ answer newbie questions, and generally made Django that much better: Thomas Stromberg <tstromberg@google.com> Thomas Tanner <tanner@gmx.net> tibimicu@gmx.net + Ties Jan Hefting <hello@tiesjan.com> Tim Allen <tim@pyphilly.org> Tim Givois <tim.givois.mendez@gmail.com> Tim Graham <timograham@gmail.com> diff --git a/django/forms/formsets.py b/django/forms/formsets.py index a89c35599f..b8e0d62fd9 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -333,7 +333,7 @@ class BaseFormSet: self._non_form_errors. """ self._errors = [] - self._non_form_errors = self.error_class() + self._non_form_errors = self.error_class(error_class='nonform') empty_forms_count = 0 if not self.is_bound: # Stop further processing. @@ -380,7 +380,10 @@ class BaseFormSet: # Give self.clean() a chance to do cross-form validation. self.clean() except ValidationError as e: - self._non_form_errors = self.error_class(e.error_list) + self._non_form_errors = self.error_class( + e.error_list, + error_class='nonform' + ) def clean(self): """ diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index f0742db7bd..ee3922c9b6 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -218,6 +218,10 @@ Forms error message. This allows custom error messages to use the ``%(value)s`` placeholder. +* :class:`~django.forms.formsets.BaseFormSet` now renders non-form errors with + an additional class of ``nonform`` to help distinguish them from + form-specific errors. + Generic Views ~~~~~~~~~~~~~ diff --git a/docs/topics/forms/formsets.txt b/docs/topics/forms/formsets.txt index 1f2c7c3fad..0281b6a4d6 100644 --- a/docs/topics/forms/formsets.txt +++ b/docs/topics/forms/formsets.txt @@ -365,6 +365,20 @@ The formset ``clean`` method is called after all the ``Form.clean`` methods have been called. The errors will be found using the ``non_form_errors()`` method on the formset. +Non-form errors will be rendered with an additional class of ``nonform`` to +help distinguish them from form-specific errors. For example, +``{{ formset.non_form_errors }}`` would look like: + +.. code-block:: html+django + + <ul class="errorlist nonform"> + <li>Articles in a set must have distinct titles.</li> + </ul> + +.. versionchanged:: 4.0 + + The additional ``nonform`` class was added. + Validating the number of forms in a formset =========================================== diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 880ba0b85f..b277476296 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -3348,7 +3348,10 @@ class AdminViewListEditable(TestCase): response = self.client.post(reverse('admin:admin_views_person_changelist'), data) non_form_errors = response.context['cl'].formset.non_form_errors() self.assertIsInstance(non_form_errors, ErrorList) - self.assertEqual(str(non_form_errors), str(ErrorList(["Grace is not a Zombie"]))) + self.assertEqual( + str(non_form_errors), + str(ErrorList(['Grace is not a Zombie'], error_class='nonform')), + ) def test_list_editable_ordering(self): collector = Collector.objects.create(id=1, name="Frederick Clegg") diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py index 889560aa74..5afb816f7f 100644 --- a/tests/forms_tests/tests/test_formsets.py +++ b/tests/forms_tests/tests/test_formsets.py @@ -337,6 +337,10 @@ class FormsFormsetTestCase(SimpleTestCase): formset = ChoiceFormSet(data, auto_id=False, prefix='choices') self.assertFalse(formset.is_valid()) self.assertEqual(formset.non_form_errors(), ['Please submit at most 1 form.']) + self.assertEqual( + str(formset.non_form_errors()), + '<ul class="errorlist nonform"><li>Please submit at most 1 form.</li></ul>', + ) def test_formset_validate_min_flag(self): """ @@ -359,6 +363,11 @@ class FormsFormsetTestCase(SimpleTestCase): formset = ChoiceFormSet(data, auto_id=False, prefix='choices') self.assertFalse(formset.is_valid()) self.assertEqual(formset.non_form_errors(), ['Please submit at least 3 forms.']) + self.assertEqual( + str(formset.non_form_errors()), + '<ul class="errorlist nonform"><li>' + 'Please submit at least 3 forms.</li></ul>', + ) def test_formset_validate_min_unchanged_forms(self): """ @@ -983,6 +992,11 @@ class FormsFormsetTestCase(SimpleTestCase): formset = FavoriteDrinksFormSet(data, prefix='drinks') self.assertFalse(formset.is_valid()) self.assertEqual(formset.non_form_errors(), ['You may only specify a drink once.']) + self.assertEqual( + str(formset.non_form_errors()), + '<ul class="errorlist nonform"><li>' + 'You may only specify a drink once.</li></ul>', + ) def test_formset_iteration(self): """Formset instances are iterable.""" |
