Фильтрация связанных цветов в Django Admin на основе выбора продукта

Заявление о проблеме:

Я работаю над проектом Django, в котором у меня есть две модели: Product и Color. Модель Product имеет отношения «многие-ко-многим» с моделью Color через поле product_varients. Моя цель - отфильтровать доступные цвета в интерфейсе администратора Django на основе выбранного продукта. В частности, я хочу, чтобы при создании или редактировании Color поле product_varients показывало только те цвета, которые еще не связаны с этим товаром

Модели:

Вот соответствующие части моих моделей:

from django.db import models
from shortuuid.django.fields import ShortUUIDField

class Color(models.Model):
    coid = ShortUUIDField(length=10, max_length=100, prefix="col", alphabet="abcdefgh")
    name = models.CharField(max_length=20)
    product_varients = models.ManyToManyField('Product', related_name='color_variants', blank=True)

    def __str__(self):
        return self.name

class Product(models.Model):
    pid = ShortUUIDField(length=10, max_length=100, prefix="prd", alphabet="abcdef")
    title = models.CharField(max_length=100, default="Apple")
    color = models.ManyToManyField(Color, blank=True)

    def __str__(self):
        return self.title

Текущая реализация:

В моей admin.py модели я реализовал пользовательскую форму для Color модели, чтобы фильтровать поле product_varients. Вот соответствующий код:

class ColorAdminForm(forms.ModelForm):
    class Meta:
        model = Color
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(ColorAdminForm, self).__init__(*args, **kwargs)
        
        if self.instance.pk:  # Editing an existing color
            self.fields['product_varients'].queryset = Product.objects.exclude(
                color=self.instance  # Exclude products that already have this color
            )
        else:  # Creating a new color
            self.fields['product_varients'].queryset = Product.objects.all()

class ColorAdmin(admin.ModelAdmin):
    form = ColorAdminForm

Встречающаяся проблема:

Хотя логика фильтрации кажется правильной, я сталкиваюсь со следующими проблемами:

  1. Поле product_varients отображается неправильно, когда я пытаюсь создать или отредактировать Color. Оно показывает все товары вместо того, чтобы исключить те, которые уже связаны с цветом.

  2. Я хочу убедиться, что при создании нового Color он показывает только те товары, которые еще не связаны с этим цветом.

Вопросы:

  1. Как правильно отфильтровать поле product_varients в админке Django, чтобы в нем отображались только товары, которые еще не связаны с выбранным цветом?

  2. Есть ли лучший подход для достижения этой фильтрации в интерфейсе администратора Django?

Основная проблема, с которой вы столкнулись, связана с тем, как вы фильтруете продукты для существующих цветов и для новых цветов. Однако ваша текущая реализация не обрабатывает корректный логин исключения, потому что .exclude(color = self.instance) не делает того, что вы ожидаете. Вместо этого ищите прямую связь между продуктом и цветом, но в реальности это многие ко многим через product_variants

Необходимо изменить запрос product_varients Поле показывает только те товары, которые еще не связаны с текущим цветом, или с другими цветами, если это новый цвет.

class ColorAdminForm(forms.ModelForm):
    class Meta:
        model = Color
        fields = '__all__'
    def __init__(self, *args, **kwargs):
        super(ColorAdminForm, self).__init__(*args, **kwargs)
        
          if self.instance.pk:  # Editing an existing color
            self.fields['product_varients'].queryset = 
          Product.objects.exclude(
                color_variants=self.instance
            )
          else:  
           self.fields['product_varients'].queryset=Product.objects.exclude(
                color__isnull=False  
            )         

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