[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
This commit is contained in:
parent
3543e128df
commit
f7e52d449a
|
@ -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())
|
||||
|
||||
|
|
|
@ -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 ######################################################
|
||||
|
||||
|
|
Loading…
Reference in New Issue