Как узнать количество продуктов в категории через django orm?

вот есть такие модельки обычные
# coding: utf-8
from django.db import models


class Category(models.Model):
    name = models.CharField('Категория товара', max_length=64)


class Product(models.Model):
    category = models.ForeignKey(Category, verbose_name='Категория')
    name = models.CharField('Наименование товара', max_length=128)
    price = models.DecimalField('Цена единицы, руб.', max_digits=10, decimal_places=2)


как с помощью Django ORM выбрать товары, цена которых больше или равна 100 руб., сгруппировать по категориям и посчитать количество товаров в каждой категории?

делаю так:
Category.objects.filter(product__price__gte=100).annotate(product_name=F('product__name'), product_price=F('product__price'), count=Count('product'))

но выходит, что count 1 всегда

а есть сделать так
Category.objects.filter(product__price__gte=100).annotate(count=Count('product'))

то count показывает то что надо
  • Вопрос задан
  • 4494 просмотра
Решения вопроса 1
рекомендую вам не парится с annotate, у него есть один нюанс(который у вас практически не проявляется) в GROUP BY будут добавлены все поля из модели, если их не ограничивать через only (у вас это [id, name]), что может оказаться крайне медленным, если также вытягиваете related связи они тоже будут в GROUP BY.

я надеюсь, что у вас не старая джанго и пострге в качестве базы
сategories = Category.objects.filter(
    product__price__gte=100
).prefetch_related(
    Prefetch('product_set', queryset=Product.objects.filter(price__gte=100))
).distinct('id')
for category in сategories:
    products = category.product_set.all()
    print(category.name, len(products), products)

будет ровно два запроса
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Хотите получить товары, а выборку делаете по категориям. Product.objects.filter ...
Ответ написан
winordie
@winordie
Лучшая документация -- исходники
category_products = Category.objects.annotate(c=Count('product')).order_by('-c')
for category in category_products:
     print(category.c, category.product_set.all())

Это не работает у вас?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы