Django formset cleaned_data empty when submitted f

2019-05-07 11:46发布

问题:

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?

回答1:

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.



回答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