G
G
Gasoid2015-12-14 12:02:50
Django
Gasoid, 2015-12-14 12:02:50

How to get the number of products in a category via django orm?

there are such ordinary models

# 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)

how to use Django ORM to select products whose price is greater than or equal to 100 rubles, group them into categories and count the number of products in each category?
I do like this:
Category.objects.filter(product__price__gte=100).annotate(product_name=F('product__name'), product_price=F('product__price'), count=Count('product'))

but it turns out that count 1 is always
a do so
Category.objects.filter(product__price__gte=100).annotate(count=Count('product'))

then count shows what you need

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Artem Klimenko, 2015-12-14
@Gasoid

I recommend that you don’t bother with annotate, it has one nuance (which practically doesn’t appear for you) in GROUP BY all fields from the model will be added if they are not limited through only (you have this [id, name]), which may turn out to be extremely slow, if you also pull related links, they will also be in GROUP BY.
i hope you don't have old django and postrge as a base

с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)

there will be exactly two requests

V
Viktor Melnikov, 2015-12-14
@Viteran33

You want to get goods, and you make a selection by category. product.objects.filter ...

O
Oscar Django, 2015-12-14
@winordie

category_products = Category.objects.annotate(c=Count('product')).order_by('-c')
for category in category_products:
     print(category.c, category.product_set.all())

Is this not working for you?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question