Skip to content

Commit

Permalink
Fixed #18574 -- Make BaseFormSet.is_valid call its underlying forms' …
Browse files Browse the repository at this point in the history
…is_valid

Thanks Simon Charette for the report and the initial patch.
  • Loading branch information
foonicorn authored and claudep committed Dec 6, 2012
1 parent 34dcf51 commit 66dfcc1
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
5 changes: 2 additions & 3 deletions django/forms/formsets.py
Expand Up @@ -267,7 +267,7 @@ def _should_delete_form(self, form):

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
Expand All @@ -282,8 +282,7 @@ def is_valid(self):
# 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):
Expand Down
21 changes: 21 additions & 0 deletions tests/regressiontests/forms/tests/formsets.py
Expand Up @@ -856,6 +856,27 @@ class CustomErrorList(ErrorList):
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
Expand Down

0 comments on commit 66dfcc1

Please sign in to comment.