summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Kocherhans <joseph@jkocherhans.com>2009-03-30 19:36:19 +0000
committerJoseph Kocherhans <joseph@jkocherhans.com>2009-03-30 19:36:19 +0000
commit08056572e89a9ac1c958ef7d47efe576c76116da (patch)
tree3e0b47592e03b2021be53be30fabf50212f81cda
parent78cbc3acfa6d8ccbb8414ac04e477922822c8e50 (diff)
Fixed #9587. Formset.is_valid() now returns True if an invalid form is marked for deletion. Thanks for the test and intial patch, kratorius.
Note that this leaves the form and formset errors alone. Those forms still have errors, it's just that it doesn't matter that they're invalid in the context of the formset and deletion. Also fixed #9665 while I was in there. Thanks, mark_hildreth. git-svn-id: http://code.djangoproject.com/svn/django/trunk@10206 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 955b41a437..3421b56e8c 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')
@@ -152,7 +152,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__)
@@ -221,8 +221,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 ######################################################