Opened 16 years ago
Closed 15 years ago
#11418 closed (fixed)
formset.cleaned_data raises AttributeError when is_valid is True
| Reported by: | Andy Durdin | Owned by: | nobody |
|---|---|---|---|
| Component: | Forms | Version: | dev |
| Severity: | Keywords: | sprintSep2010 | |
| Cc: | me@… | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
With a formset with no initial forms and empty extra forms, formset.is_valid() returns True, but formset.cleaned_data raises an AttributeError.
This can be found with the examples from the formsets docs:
>>> from django import forms
>>> class ArticleForm(forms.Form):
... title = forms.CharField()
... pub_date = forms.DateField()
...
>>> from django.forms.formsets import formset_factory
>>> ArticleFormSet = formset_factory(ArticleForm)
>>> formset = ArticleFormSet({})
>>>
>>> formset.is_valid()
True
>>> formset.errors
[{}]
>>> formset.cleaned_data
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/andy/dev/django/dj/django/forms/formsets.py", line 128, in _get_cleaned_data
return [form.cleaned_data for form in self.forms]
AttributeError: 'ArticleForm' object has no attribute 'cleaned_data'
Attachments (2)
Change History (11)
comment:1 by , 16 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:2 by , 16 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:3 by , 16 years ago
| Has patch: | set |
|---|
comment:4 by , 16 years ago
| Owner: | changed from to |
|---|---|
| Status: | assigned → new |
comment:5 by , 15 years ago
| Owner: | changed from to |
|---|---|
| Patch needs improvement: | set |
After coming back to this and speaking with kmtracy I'm not sure the described functionality is correct. A valid formset should have cleaned_data attribute but a formset passed an empty dict should raise a ValidationError "ManagementForm data is missing or has been tampered with". The formset validation needs some work but I believe the docs need an update as well.
comment:6 by , 15 years ago
| Owner: | changed from to |
|---|---|
| Patch needs improvement: | unset |
New patch which updates the validation logic and the docs around formsets. This does introduce a small backwards incompatible change in that previously passing an empty dict would validate but now it will throw and exception that the Management Form is invalid which I believe is the more intuitive behavior. Let me know if you think it needs some more work.
comment:7 by , 15 years ago
| Owner: | changed from to |
|---|
Removing myself as owner since I'm not going to be able to finish this tonight and then I'll be gone, so if someone else wants to take a look feel free.
comment:8 by , 15 years ago
| Keywords: | sprintSep2010 added |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
comment:9 by , 15 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
This formset does have a form in it and it is not valid. The formset itself is bound but the form is not bound (and hence not valid).
>>> from django import forms >>> class ArticleForm(forms.Form): ... title = forms.CharField() ... pub_date = forms.DateField() ... >>> from django.forms.formsets import formset_factory >>> ArticleFormSet = formset_factory(ArticleForm) >>> formset = ArticleFormSet({}) >>> formset.forms [<__main__.ArticleForm object at 0x94636cc>] >>> formset.forms[0].is_valid() False >>> formset.is_bound True >>> formset.forms[0].is_bound FalseI think the problem is in the BaseFormSet._construct_form:
def _construct_form(self, i, **kwargs): """ Instantiates and returns the i-th form instance in a formset. """ defaults = {'auto_id': self.auto_id, 'prefix': self.add_prefix(i)} if self.data or self.files: defaults['data'] = self.data defaults['files'] = self.files ...if self.data or self.files:should beif self.is_bound:because the empty data dictionary is not being passed down to the forms.