Skip to content

Commit

Permalink
Fixed #11404. Added FormSet.has_changed, for consistancy with ``F…
Browse files Browse the repository at this point in the history
…orm.has_changed``. Thanks to michelts for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16773 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
alex committed Sep 10, 2011
1 parent 01b0eb5 commit d14bf8c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 1 deletion.
6 changes: 6 additions & 0 deletions django/forms/formsets.py
Expand Up @@ -300,6 +300,12 @@ def clean(self):
"""
pass

def has_changed(self):
"""
Returns true if data in any form differs from initial.
"""
return any(form.has_changed() for form in self)

def add_fields(self, form, index):
"""A hook for adding extra fields on to each form instance."""
if self.can_order:
Expand Down
14 changes: 14 additions & 0 deletions docs/topics/forms/formsets.txt
Expand Up @@ -150,6 +150,20 @@ As we can see, ``formset.errors`` is a list whose entries correspond to the
forms in the formset. Validation was performed for each of the two forms, and
the expected error message appears for the second item.

We can also check if form data differs from the initial data (i.e. the form was
sent without any data)::

>>> data = {
... 'form-TOTAL_FORMS': u'1',
... 'form-INITIAL_FORMS': u'0',
... 'form-MAX_NUM_FORMS': u'',
... 'form-0-title': u'',
... 'form-0-pub_date': u'',
... }
>>> formset = ArticleFormSet(data)
>>> formset.has_changed()
False

.. _understanding-the-managementform:

Understanding the ManagementForm
Expand Down
29 changes: 28 additions & 1 deletion tests/regressiontests/forms/tests/formsets.py
Expand Up @@ -73,9 +73,11 @@ def test_basic_formset(self):
self.assertTrue(formset.is_valid())
self.assertEqual([form.cleaned_data for form in formset.forms], [{'votes': 100, 'choice': u'Calexico'}])

# If a FormSet was not passed any data, its is_valid method should return False.
# If a FormSet was not passed any data, its is_valid and has_changed
# methods should return False.
formset = ChoiceFormSet()
self.assertFalse(formset.is_valid())
self.assertFalse(formset.has_changed())

def test_formset_validation(self):
# FormSet instances can also have an error attribute if validation failed for
Expand All @@ -93,6 +95,31 @@ def test_formset_validation(self):
self.assertFalse(formset.is_valid())
self.assertEqual(formset.errors, [{'votes': [u'This field is required.']}])

def test_formset_has_changed(self):
# FormSet instances has_changed method will be True if any data is
# passed to his forms, even if the formset didn't validate
data = {
'choices-TOTAL_FORMS': '1', # the number of forms rendered
'choices-INITIAL_FORMS': '0', # the number of forms with initial data
'choices-MAX_NUM_FORMS': '0', # max number of forms
'choices-0-choice': '',
'choices-0-votes': '',
}
blank_formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertFalse(blank_formset.has_changed())

# invalid formset test
data['choices-0-choice'] = 'Calexico'
invalid_formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertFalse(invalid_formset.is_valid())
self.assertTrue(invalid_formset.has_changed())

# valid formset test
data['choices-0-votes'] = '100'
valid_formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertTrue(valid_formset.is_valid())
self.assertTrue(valid_formset.has_changed())

def test_formset_initial_data(self):
# We can also prefill a FormSet with existing data by providing an ``initial``
# argument to the constructor. ``initial`` should be a list of dicts. By default,
Expand Down

0 comments on commit d14bf8c

Please sign in to comment.