Django admin и встроенные связанные модели - фильтрация

Я создаю проект электронной коммерции на Django. Изначально у меня была наивная модель Product, что позволило мне двигаться дальше. Но позже я добавил классы/таблицы ProductType, ProductSpecification (с ForeignKey к Type) и ProductSpecificationValue (с ForeignKey к Specification и Product). Пример использования должен быть очевиден: скажем, у меня есть продукт типа shirt ProductType, который может быть разных цветов. Это означает, что спецификация color.

Сначала я создаю два типа продукта, скажем, рубашку и книгу. Каждый из них имеет спецификацию цена и спецификацию вес. Кроме того, у Shirt есть спецификация color. Проблема в том, что когда я создаю новый продукт и выбираю любой тип, в выпадающем списке для выбора спецификации есть 5 значений для выбора - две цены, два веса и цвет.

Теперь, я не знаю, является ли это реальной проблемой - но это точно очень запутанно. Я понимаю, что перед сохранением продукта, Django Admin UI еще не знает, какого типа он будет, поэтому не может ограничить спецификации только выбранным типом. Однако, даже после сохранения продукта (который требует выбора типа), и последующей попытки его редактирования, выпадающий список спецификаций все еще представляет мне все 5 вариантов. База данных показывает вероятную причину:

sqlite> select * from inventory_productspecification;
1|price |1
2|weight|1
3|price |2
4|weight|2
5|color |2

этот запрос не фильтрует по идентификатору типа (здесь 1 против 2). Я предполагаю, что некоторые изменения в admin.py могут позаботиться об этом? Мой довольно простой:

class ProductSpecificationInline(admin.TabularInline):
    model = ProductSpecification


@ admin.register(ProductType)
class ProductTypeAdmin(admin.ModelAdmin):
    inlines = [
        ProductSpecificationInline,
    ]


class ProductSpecificationValueInline(admin.TabularInline):
    model = ProductSpecificationValue


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = [
        ProductSpecificationValueInline,
    ]

(спасибо за ваше время)

Похоже, что нужно решить несколько проблем: #1 - процесс создания объекта, и #2 - отображение ProductSpecificationValues, которые связаны с Product'ProductType.

#1: Не показывайте ProductSpecificationValueInline при создании продукта. Пользователь должен иметь возможность установить это значение только после создания продукта и установки ProductType.

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = [
        ProductSpecificationValueInline,
    ]

    def get_inlines(self, request, obj):
        if not obj.id or not obj.product_type:
            return []  # ... then don't show any inlines
        return self.inlines

#2: ProductSpecificationValueInline должен показывать только те значения спецификации, которые связаны с типом продукта.

class ProductSpecificationValueInline(admin.TabularInline):
    model = ProductSpecificationValue

    def get_formset(self, request, obj=None, **kwargs):
        inline_formset = super().get_formset(request, obj, **kwargs)
        # I don't know what you named your field(s), but this illustrates the concept
        # of changing the queryset that is used to populate the choices for this field
        qs = inline_formset.base_fields['product_specification'].queryset
        qs = qs.filter(product_type=obj.product_type)
        inline_formset.base_fields['product_specification'].queryset = qs
        return inline_formset

Очевидно, что это может не на 100% соответствовать вашим моделям (например, используете ли вы поле ManyToMany для значений ProductSpecification продукта? И каковы имена полей в моделях?), но общий принцип остается тем же: в своем встроенном классе вы переопределите метод get_formset и измените набор запросов для соответствующего поля (полей) формы.

Рад помочь вам немного приблизиться, если это необходимо, но нужно увидеть код для ваших моделей.

Вернуться на верх