lightstrike
lightstrike

Reputation: 974

Django validation error triggered with initial data in modelformset_factory

I'm currently running Django 1.4.

When I'm creating a modelformset and provide an initial value to the extra form, Django then runs validation against it and finds that the other required fields are empty and thus throws a validation error.

My code looks something like this:

QueryFormset = modelformset_factory(Query, extra=1, 
    can_delete=True, form=QueryForm
)

if request.method == "POST":
    qformset = QueryFormset(request.POST)
    if qformset.is_valid():
        qformset.save()
    else:
        # This is where we go when the formset is saved without
        # any values inserted into the extra form
else:
    qformset = QueryFormset(
        queryset=Query.objects.filter(user=request.user),
        initial=[{'user': request.user}]
    )

If I just click save without making any changes to the values of the form (existing forms, or to the extra form) the formset is marked as invalid because the extra form has something in the user field, but is missing the other required fields.

How do I make Django let this pass by? It should throw away the extra form as nothing there has been changed.

Upvotes: 4

Views: 1534

Answers (1)

Aaron
Aaron

Reputation: 2679

I'm not saying this is the best solution, but I was able to work around this problem by modifying the form's 'is_bound' attribute. This is an internal flag indicating whether the form has something worth validating (from what I can tell).

initial_data = [{...},]
if request.POST:
    formset = ContactFormSet(request.POST, initial=initial_data)

    valid = True
    for form in formset:
        if not form.has_changed():
            # we don't want to complain about an unmodified form.
            form.is_bound = False
        if not form.is_valid():
            valid = False

    if valid:
        for form in formset:
            if form.has_changed():
                # do stuff

else:
    formset = ContactFormSet(initial=initial_data)

...

It'd definitely be nicer to integrate this workaround into the form/formset itself, rather than the view, but I don't need this behaviour often, so it's good enough for me.

Upvotes: 2

Related Questions