Django admin inline formset

I am trying to implement an inline form for the Product model in the admin interface. In addition to displaying forms for existing ProductAttribute relationships, I want to automatically add forms for all attributes associated with the category of the product being edited. However, the problem is that, although the forms are displayed correctly, saving the form does not create a new ProductAttribute relationship in the database, and the cleaned_data for these forms is empty.

admin.py:

...
class ProductAttributeInline(admin.TabularInline):
    model = ProductAttribute
    formset = ProductAttributeInlineFormset
    fields = ('attribute', 'value')
    readonly_fields = ('attribute',)

    def has_add_permission(self, request, obj=None):
        return False


u/admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = (
        'name',
        'category',
        'price',
        'sku',
        'created_at',
        'updated_at'
    )
    search_fields = ('name', 'sku')
    list_filter = ('category',)
    inlines = (ProductAttributeInline,)
...

forms.py:

from django import forms

from .models import ProductAttribute


class ProductAttributeInlineFormset(forms.models.BaseInlineFormSet):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance and self.instance.pk:
            category = self.instance.category
            if category:
                attributes = category.attributes.all()
                existing_attributes = set(
                    self.queryset.values_list('attribute', flat=True)
                )
                extra_forms_count = 0
                for attribute in attributes:
                    if attribute.id not in existing_attributes:
                        form = self._construct_form(
                            len(self.forms),
                            instance=ProductAttribute(
                                product=self.instance,
                                attribute=attribute,
                            ),
                        )
                        self.forms.append(form)
                        extra_forms_count += 1
                self.extra = extra_forms_count

Welcome @Qswxexrt !

Please post the models involved to help us understand the relationships among them.

I’ve wasted so much time trying to figure this out…


from django import forms

from .models import ProductAttribute


class ProductAttributeInlineFormset(forms.models.BaseInlineFormSet):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance and self.instance.pk:
            category = self.instance.category
            if category:
                attributes = category.attributes.all()
                existing_attributes = set(
                    self.queryset.values_list('attribute', flat=True)
                )
                for attribute in attributes:
                    if attribute.id not in existing_attributes:
                        form = self._construct_form(
                            len(self.forms),
                            instance=ProductAttribute(
                                product=self.instance,
                                attribute=attribute,
                            ),
                        )
                        form.has_changed = lambda: True
                        form.empty_permitted = True
                        self.forms.append(form)

    def clean(self):
        super().clean()
        for form in self.forms:
            if form.empty_permitted:
                form._errors = {}
                form.cleaned_data = {}

    def save(self, commit=True):
        instances = super().save(commit=False)
        instances = [instance for instance in instances if instance.value]
        if commit:
            for instance in instances:
                instance.save()
        return instances