Django formset cleaned_data empty when submitted form unchanged
Asked Answered
D

2

6

I've been experiencing a weird problem, regarding Django 1.4 and formsets: when the submitted data is unchanged, the cleaned_data field of the formset is empty, even if the formset itself passes the validation.

Here is an example:

forms.py:

class NameForm(forms.Form):
    name = forms.CharField(required=False, initial='Foo')

views.py:

def welcome(request):

    Formset = formset_factory(NameForm, extra=1)
    if request.method == 'POST':
        formset = Formset(request.POST)
        print '1.Formset is valid?', formset.is_valid()
        print '2.Formset', formset
        print '3.Formset cleaned_data', formset.cleaned_data
    else:
        formset = Formset()
    return render_to_response('template.html', locals())

Although formset is valid, and it actually contains data, line 3 prints a list of an empty dictionary, unless I've actually changed the initial value in the field.

This seems weird to me, but I'm probably doing something wrong. Any help?

Dmso answered 31/3, 2012 at 15:31 Comment(1)
Can you show your template code?Glanders
M
11

A formset renders bunch of forms as well as several hidden input fields holding info such as max number of forms. Thus a correctly POSTed formset always contains data.

And, the initial 'Foo' inside CharField name is the reason that formset got empty dictionary. When empty_permitted of a form is set to True, and all items of the form equals to its initial value, Django will treat the form as empty and set its cleaned_data to be empty dict. The empty_permitted defaults to False, formset will set it to True for extra forms. Thus after you clicked submit w/o editing the value 'Foo', the form instance was treated as empty, hence the formset wrapping the form got an empty cleaned_data.

Margravine answered 31/3, 2012 at 16:28 Comment(1)
Just helped me solve a wicked bug after much head-scratching – thanks!Nichani
F
2

This happened to me. @okm is correct but it's not clear from his answer how to fix it. See this answer for a solution:

class MyModelFormSet(BaseModelFormSet):
    def __init__(self, *args, **kwargs):
        super(MyModelFormSet, self).__init__(*args, **kwargs)
        for form in self.forms:
            form.empty_permitted = False
Favian answered 17/12, 2013 at 23:3 Comment(1)
Thanks for providing the code – very helpful. Ran into this issue earlier and it was quite infuriating!Nichani

© 2022 - 2024 — McMap. All rights reserved.