summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Kocherhans <joseph@jkocherhans.com>2009-03-30 22:03:20 +0000
committerJoseph Kocherhans <joseph@jkocherhans.com>2009-03-30 22:03:20 +0000
commitf7e52d449a62330a5c0e41fd4858a99039e6d605 (patch)
tree6794f4c1a4f42d4c4b23c7ccbb850e4f3dd303dd
parent3543e128df87abd31816f6914503c3b9621d0388 (diff)
[1.0.X] Fixed #9587. Formset.is_valid() now returns True if an invalid form is marked for deletion. Backport of r10206 from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@10219 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/forms/formsets.py21
-rw-r--r--tests/regressiontests/forms/formsets.py30
2 files changed, 46 insertions, 5 deletions
diff --git a/django/forms/formsets.py b/django/forms/formsets.py
index 7a5cb8a439..81353070a9 100644
--- a/django/forms/formsets.py
+++ b/django/forms/formsets.py
@@ -4,7 +4,7 @@ from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
from fields import IntegerField, BooleanField
from widgets import Media, HiddenInput
-from util import ErrorList, ValidationError
+from util import ErrorList, ErrorDict, ValidationError
__all__ = ('BaseFormSet', 'all_valid')
@@ -140,7 +140,7 @@ class BaseFormSet(StrAndUnicode):
def _get_ordered_forms(self):
"""
Returns a list of form in the order specified by the incoming data.
- Raises an AttributeError if deletion is not allowed.
+ Raises an AttributeError if ordering is not allowed.
"""
if not self.is_valid() or not self.can_order:
raise AttributeError("'%s' object has no attribute 'ordered_forms'" % self.__class__.__name__)
@@ -209,8 +209,21 @@ class BaseFormSet(StrAndUnicode):
# We loop over every form.errors here rather than short circuiting on the
# first failure to make sure validation gets triggered for every form.
forms_valid = True
- for errors in self.errors:
- if bool(errors):
+ for i in range(0, self._total_form_count):
+ form = self.forms[i]
+ if self.can_delete:
+ # The way we lookup the value of the deletion field here takes
+ # more code than we'd like, but the form's cleaned_data will
+ # not exist if the form is invalid.
+ field = form.fields[DELETION_FIELD_NAME]
+ prefix = form.add_prefix(DELETION_FIELD_NAME)
+ value = field.widget.value_from_datadict(self.data, self.files, prefix)
+ should_delete = field.clean(value)
+ if should_delete:
+ # 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
return forms_valid and not bool(self.non_form_errors())
diff --git a/tests/regressiontests/forms/formsets.py b/tests/regressiontests/forms/formsets.py
index 4fd0c17032..c3c89d078d 100644
--- a/tests/regressiontests/forms/formsets.py
+++ b/tests/regressiontests/forms/formsets.py
@@ -241,7 +241,7 @@ data.
# FormSets with deletion ######################################################
-We can easily add deletion ability to a FormSet with an agrument to
+We can easily add deletion ability to a FormSet with an argument to
formset_factory. This will add a boolean field to each form instance. When
that boolean field is True, the form will be in formset.deleted_forms
@@ -286,6 +286,34 @@ True
>>> [form.cleaned_data for form in formset.deleted_forms]
[{'votes': 900, 'DELETE': True, 'choice': u'Fergie'}]
+If we fill a form with something and then we check the can_delete checkbox for
+that form, that form's errors should not make the entire formset invalid since
+it's going to be deleted.
+
+>>> class CheckForm(Form):
+... field = IntegerField(min_value=100)
+
+>>> data = {
+... 'check-TOTAL_FORMS': '3', # the number of forms rendered
+... 'check-INITIAL_FORMS': '2', # the number of forms with initial data
+... 'check-0-field': '200',
+... 'check-0-DELETE': '',
+... 'check-1-field': '50',
+... 'check-1-DELETE': 'on',
+... 'check-2-field': '',
+... 'check-2-DELETE': '',
+... }
+>>> CheckFormSet = formset_factory(CheckForm, can_delete=True)
+>>> formset = CheckFormSet(data, prefix='check')
+>>> formset.is_valid()
+True
+
+If we remove the deletion flag now we will have our validation back.
+
+>>> data['check-1-DELETE'] = ''
+>>> formset = CheckFormSet(data, prefix='check')
+>>> formset.is_valid()
+False
# FormSets with ordering ######################################################