Search code examples
djangodjango-forms

Inline Form Validation in Django


I would like to make an entire inline formset within an admin change form compulsory. So in my current scenario when I hit save on an Invoice form (in Admin) the inline Order form is blank. I'd like to stop people creating invoices with no orders associated.

Anyone know an easy way to do that?

Normal validation like (required=True) on the model field doesn't appear to work in this instance.


Solution

  • The best way to do this is to define a custom formset, with a clean method that validates that at least one invoice order exists.

    class InvoiceOrderInlineFormset(forms.models.BaseInlineFormSet):
        def clean(self):
            # get forms that actually have valid data
            count = 0
            for form in self.forms:
                try:
                    if form.cleaned_data:
                        count += 1
                except AttributeError:
                    # annoyingly, if a subform is invalid Django explicity raises
                    # an AttributeError for cleaned_data
                    pass
            if count < 1:
                raise forms.ValidationError('You must have at least one order')
    
    class InvoiceOrderInline(admin.StackedInline):
        formset = InvoiceOrderInlineFormset
    
    
    class InvoiceAdmin(admin.ModelAdmin):
        inlines = [InvoiceOrderInline]