Как я могу запросить все продукты с их вариативными атрибутами?

У меня есть следующая схема базы данных:

database schema

Django models:

class Product(models.Model):
    name = models.CharField(max_length=150)
    # price and so on

class Size(models.Model):
    value = models.CharField(max_length=20)
    
class Color(models.Model):
    value = models.CharField(max_length=20)

class Variation(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="variations")
    size = models.ForeignKey(Size, on_delete=models.CASCADE)
    color = models.ForeignKey(Color, on_delete=models.CASCADE)

Так я могу написать:

product.variations

Но я также хочу иметь возможность писать

product.sizes

product.colors

чтобы получить все размеры или цвета, которые имеет этот продукт в таблице вариаций

Проблема, которую я пытаюсь решить: У меня есть список карточек товаров. И в каждой карточке есть варианты размеров и цветов для выбора и добавления в корзину пользователя. Я хочу показать пользователю размеры и цвета, которые есть у этого конкретного товара в базе данных, а не перечислять все размеры и цвета из базы данных.

enter image description here

Но вариации могут иметь дубликаты, например, рассмотрим эти комбинации для некоторого случайного продукта:

размер - 40, цвет - красный

размер - 42, цвет - зеленый

размер - 44, цвет - красный (снова)

размер - 42 (снова), цвет - серый

Я хочу показать пользователю размеры: 40, 42, 44

цвета: красный, зеленый, серый

На данный момент я показываю все из них с дубликатами, например

размеры: 40, 42, 44, 42

цвета: красный, зеленый, красный, серый

Выдает этот код, и я не знаю, как его переписать:

products: QuerySet[Product] = (
    Product.objects
        .prefetch_related("variations__size")
        .prefetch_related("variations__color")
        .all()[:15]
)

Затем я перебираю товары в своем шаблоне без дополнительных запросов типа

{% for variation in product.variations.all %}
    variation.size.value
{% endfor %}

Кажется, я нашел решение:

Я использовал объект Prefetch и его 3-й аргумент to_attr: https://docs.djangoproject.com/en/4.0/ref/models/querysets/#django.db.models.Prefetch

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