From f5c6295797b8332134fd89e0209a18a1d1d45e0c Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Mon, 18 Jul 2016 17:30:55 +0300 Subject: [PATCH] Fixed #26844 -- Made formset's validate_min validation ignore empty forms. --- django/forms/formsets.py | 6 +++++- tests/forms_tests/tests/test_formsets.py | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/django/forms/formsets.py b/django/forms/formsets.py index 166a6adaebd..9e185de1b34 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -336,11 +336,15 @@ class BaseFormSet(object): """ self._errors = [] self._non_form_errors = self.error_class() + empty_forms_count = 0 if not self.is_bound: # Stop further processing. return for i in range(0, self.total_form_count()): form = self.forms[i] + if not form.has_changed(): + empty_forms_count += 1 + self._errors.append(form.errors) try: if (self.validate_max and @@ -352,7 +356,7 @@ class BaseFormSet(object): code='too_many_forms', ) if (self.validate_min and - self.total_form_count() - len(self.deleted_forms) < self.min_num): + self.total_form_count() - len(self.deleted_forms) - empty_forms_count < self.min_num): raise ValidationError(ungettext( "Please submit %d or more forms.", "Please submit %d or more forms.", self.min_num) % self.min_num, diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py index 2cd86342b90..792d811f4ce 100644 --- a/tests/forms_tests/tests/test_formsets.py +++ b/tests/forms_tests/tests/test_formsets.py @@ -377,6 +377,17 @@ class FormsFormsetTestCase(SimpleTestCase): self.assertFalse(formset.is_valid()) self.assertEqual(formset.non_form_errors(), ['Please submit 3 or more forms.']) + def test_formset_validate_min_excludes_empty_forms(self): + data = { + 'choices-TOTAL_FORMS': '2', + 'choices-INITIAL_FORMS': '0', + } + ChoiceFormSet = formset_factory(Choice, extra=2, min_num=1, validate_min=True, can_delete=True) + formset = ChoiceFormSet(data, prefix='choices') + self.assertFalse(formset.has_changed()) + self.assertFalse(formset.is_valid()) + self.assertEqual(formset.non_form_errors(), ['Please submit 1 or more forms.']) + def test_second_form_partially_filled_2(self): # And once again, if we try to partially complete a form, validation will fail.