Фильтрация связанных цветов в 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
Встречающаяся проблема:
Хотя логика фильтрации кажется правильной, я сталкиваюсь со следующими проблемами:
Поле
product_varients
отображается неправильно, когда я пытаюсь создать или отредактироватьColor
. Оно показывает все товары вместо того, чтобы исключить те, которые уже связаны с цветом.Я хочу убедиться, что при создании нового
Color
он показывает только те товары, которые еще не связаны с этим цветом.
Вопросы:
Как правильно отфильтровать поле
product_varients
в админке Django, чтобы в нем отображались только товары, которые еще не связаны с выбранным цветом?Есть ли лучший подход для достижения этой фильтрации в интерфейсе администратора 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
)