Alejandro
Alejandro

Reputation: 551

Django - Add form validation to inlineformset_factory

So, I'm trying to validate some fields from an inlineformset_factory object, but I don't see how to do that in a clean way from this view (not using a Form class).

Would it be possible to override the .is_valid() method in this case?

Any help would be appreciated.

def tenant(request, id):
    tenant = Tenant.objects.get(id=id)

    DealerFormset = inlineformset_factory(Tenant, Dealer, fields=('name', 'phone_number'), extra=0)
    formset = DealerFormset(instance=tenant)

    if request.method == 'POST':
        formset = DealerFormset(request.POST, instance=tenant)
        if formset.is_valid(): # <---  How to add custom validations here?
            formset.save()                

        return redirect('tenant_details', id=tenant.id)

    context = {
        'formset': formset,
    }

    return render(request, 'tenant_details.html', context)

Upvotes: 3

Views: 1192

Answers (2)

Frederic Perron
Frederic Perron

Reputation: 798

You basically need to create your own formset based on the BaseInlineFormSet class. You can take a look at the django doc here for more information but there's nothing really complicated about it.

You would then create the formset by adding the formset to use as a parameter:

formset_factory(TestForm, formset=BaseTestFormSet)

Upvotes: 0

Abdou
Abdou

Reputation: 13274

Since you're using inlineformset_factory to create the set, I would recommend subclassing BaseInlineFormSet and implementing the cleanmethod. Once you have a custom FormSet class, you can pass that to inlineformset_factory via the formset keyword argument. The following should work with your current design:

from django.forms import (
    BaseInlineFormSet, inlineformset_factory
)

# Make a custom FormSet class and implement the clean method
# to customize the validation
class CustomInlineFormSet(BaseInlineFormSet):
    def clean():
        # Implement your custom validation here

# Use your custom FormSet class as an argument to inlineformset_factory
DealerFormset = inlineformset_factory(
    Tenant, Dealer, fields=('name', 'phone_number'),
    extra=0, formset=CustomInlineFormSet
)

DealerFormset can now be used because it has both basic and custom validations.

Upvotes: 1

Related Questions