Commit 66dfcc10 authored by Andreas Hug's avatar Andreas Hug Committed by Claude Paroz
Browse files

Fixed #18574 -- Make BaseFormSet.is_valid call its underlying forms' is_valid

Thanks Simon Charette for the report and the initial patch.
parent 34dcf51e
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -267,7 +267,7 @@ class BaseFormSet(object):

    def is_valid(self):
        """
        Returns True if form.errors is empty for every form in self.forms.
        Returns True if every form in self.forms is valid.
        """
        if not self.is_bound:
            return False
@@ -282,8 +282,7 @@ class BaseFormSet(object):
                    # This form is going to be deleted so any of its errors
                    # should not cause the entire formset to be invalid.
                    continue
            if bool(self.errors[i]):
                forms_valid = False
            forms_valid &= form.is_valid()
        return forms_valid and not bool(self.non_form_errors())

    def full_clean(self):
+21 −0
Original line number Diff line number Diff line
@@ -856,6 +856,27 @@ class FormsFormsetTestCase(TestCase):
        formset = FavoriteDrinksFormSet(error_class=CustomErrorList)
        self.assertEqual(formset.forms[0].error_class, CustomErrorList)

    def test_formset_calls_forms_is_valid(self):
        # Regression tests for #18574 -- make sure formsets call
        # is_valid() on each form.

        class AnotherChoice(Choice):
            def is_valid(self):
                self.is_valid_called = True
                return super(AnotherChoice, self).is_valid()

        AnotherChoiceFormSet = formset_factory(AnotherChoice)
        data = {
            'choices-TOTAL_FORMS': '1',  # number of forms rendered
            'choices-INITIAL_FORMS': '0',  # number of forms with initial data
            'choices-MAX_NUM_FORMS': '0',  # max number of forms
            'choices-0-choice': 'Calexico',
            'choices-0-votes': '100',
        }
        formset = AnotherChoiceFormSet(data, auto_id=False, prefix='choices')
        self.assertTrue(formset.is_valid())
        self.assertTrue(all([form.is_valid_called for form in formset.forms]))


data = {
    'choices-TOTAL_FORMS': '1', # the number of forms rendered