Skip to content

Commit e969c27

Browse files
committed
[1.1.X] Fixed #11801 -- Corrected form validation to ensure you can still get deleted_forms and ordered_forms when a form that is being deleted doesn't validate. Thanks to dantallis for the report and patch.
Backport of r12771 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.1.X@12772 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 3f7fcdd commit e969c27

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

django/forms/formsets.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def _get_deleted_forms(self):
144144
# if this is an extra form and hasn't changed, don't consider it
145145
if i >= self.initial_form_count() and not form.has_changed():
146146
continue
147-
if form.cleaned_data[DELETION_FIELD_NAME]:
147+
if self._should_delete_form(form):
148148
self._deleted_form_indexes.append(i)
149149
return [self.forms[i] for i in self._deleted_form_indexes]
150150
deleted_forms = property(_get_deleted_forms)
@@ -168,7 +168,7 @@ def _get_ordered_forms(self):
168168
if i >= self.initial_form_count() and not form.has_changed():
169169
continue
170170
# don't add data marked for deletion to self.ordered_data
171-
if self.can_delete and form.cleaned_data[DELETION_FIELD_NAME]:
171+
if self.can_delete and self._should_delete_form(form):
172172
continue
173173
self._ordering.append((i, form.cleaned_data[ORDERING_FIELD_NAME]))
174174
# After we're done populating self._ordering, sort it.
@@ -212,6 +212,15 @@ def _get_errors(self):
212212
return self._errors
213213
errors = property(_get_errors)
214214

215+
def _should_delete_form(self, form):
216+
# The way we lookup the value of the deletion field here takes
217+
# more code than we'd like, but the form's cleaned_data will
218+
# not exist if the form is invalid.
219+
field = form.fields[DELETION_FIELD_NAME]
220+
raw_value = form._raw_value(DELETION_FIELD_NAME)
221+
should_delete = field.clean(raw_value)
222+
return should_delete
223+
215224
def is_valid(self):
216225
"""
217226
Returns True if form.errors is empty for every form in self.forms.
@@ -224,13 +233,7 @@ def is_valid(self):
224233
for i in range(0, self.total_form_count()):
225234
form = self.forms[i]
226235
if self.can_delete:
227-
# The way we lookup the value of the deletion field here takes
228-
# more code than we'd like, but the form's cleaned_data will
229-
# not exist if the form is invalid.
230-
field = form.fields[DELETION_FIELD_NAME]
231-
raw_value = form._raw_value(DELETION_FIELD_NAME)
232-
should_delete = field.clean(raw_value)
233-
if should_delete:
236+
if self._should_delete_form(form):
234237
# This form is going to be deleted so any of its errors
235238
# should not cause the entire formset to be invalid.
236239
continue

tests/regressiontests/forms/formsets.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,26 @@
315315
>>> formset.is_valid()
316316
False
317317
318+
Should be able to get deleted_forms from a valid formset even if a
319+
deleted form would have been invalid.
320+
321+
>>> class Person(Form):
322+
... name = CharField()
323+
324+
>>> PeopleForm = formset_factory(
325+
... form=Person,
326+
... can_delete=True)
327+
328+
>>> p = PeopleForm(
329+
... {'form-0-name': u'', 'form-0-DELETE': u'on', # no name!
330+
... 'form-TOTAL_FORMS': 1, 'form-INITIAL_FORMS': 1,
331+
... 'form-MAX_NUM_FORMS': 1})
332+
333+
>>> p.is_valid()
334+
True
335+
>>> len(p.deleted_forms)
336+
1
337+
318338
# FormSets with ordering ######################################################
319339
320340
We can also add ordering ability to a FormSet with an agrument to
@@ -471,6 +491,26 @@
471491
>>> [form.cleaned_data for form in formset.deleted_forms]
472492
[{'votes': 900, 'DELETE': True, 'ORDER': 2, 'choice': u'Fergie'}]
473493
494+
Should be able to get ordered forms from a valid formset even if a
495+
deleted form would have been invalid.
496+
497+
>>> class Person(Form):
498+
... name = CharField()
499+
500+
>>> PeopleForm = formset_factory(
501+
... form=Person,
502+
... can_delete=True,
503+
... can_order=True)
504+
505+
>>> p = PeopleForm(
506+
... {'form-0-name': u'', 'form-0-DELETE': u'on', # no name!
507+
... 'form-TOTAL_FORMS': 1, 'form-INITIAL_FORMS': 1,
508+
... 'form-MAX_NUM_FORMS': 1})
509+
510+
>>> p.is_valid()
511+
True
512+
>>> p.ordered_forms
513+
[]
474514
475515
# FormSet clean hook ##########################################################
476516

0 commit comments

Comments
 (0)