Tommy Wolfheart
Tommy Wolfheart

Reputation: 583

Using inline in ModelForm in Django admin to validate many-to-many inline field (by overriding the clean() method)

I would like to validate a Many-to-many field in Django admin by overriding the clean method.

This thread gives a way to do that by creating a ModelForm and then doing the clean there. However, my problem is the many-to-many field is an inline i.e. instead of the widget where you have to select multiple elements, I have a tabular inline.

I would like to find out if anyone knows how to add the inlines in the ModelForm so that I can do the clean and validation. I've seen people talk about inlineformset_factory but it's always been as it relates to views.py and not the admin (and I can't figure out how I'd even go about overriding the clean method of that).

I've added some of my code below:

class ProductVariantForm(ModelForm):
    class Meta:
        model = ProductVariant

        fields = [  'name',
                    'price',
                 ]

        # I then want to be able to add something like
        # inlines = [OptionValueInline,]
        # for the inline many-to-many field. 

    def clean(self):
        # Check if list of option_values is ok.

class ProductVariantAdmin(admin.ModelAdmin):
    form = ProductVariantForm

Upvotes: 0

Views: 2267

Answers (2)

Tommy Wolfheart
Tommy Wolfheart

Reputation: 583

My solution to the problem is based on this post.

class ProductVariantOptionValueInlineFormSet(BaseInlineFormSet):
    def clean(self):
        super().clean()
        data = self.cleaned_data
        # do whatever validation on data here

class ProductVariantOptionValueInline(admin.TabularInline):
    model = ProductVariant.option_values.through
    formset = ProductVariantOptionValueInlineFormSet

class ProductVariantAdmin(admin.ModelAdmin):
    inlines = [
        ProductVariantOptionValueInline,
    ]

    exclude = ('option_values',)

Upvotes: 0

Adding an inline is a feature of the Admin itself. See this doc for more info about inlines. Afaik, you can't add an inline to just a plain form (or a ModelForm).

To check the validity of the data in an inline, you could use the form property of the InlineModelAdmin class. This way you can access the clean method of the inline form directly.

To elaborate, it is split this way because the inlines are a separate form in Django's terms, concerning different data and running separate queries. They are all submitted in one HTTP request, but that is all they have in common. So it doesn't really make sense to use the main ModelForm for the inline data.

Upvotes: 1

Related Questions