Джанго Агрегат в связанном поле с фильтром - PullRequest
0 голосов
/ 01 октября 2019

Следующая проблема:
У меня есть группы продуктов, содержащие продукты. Эти продукты могут быть видны во внешнем интерфейсе или нет. Я определяю их видимость с помощью метода frontend() (который содержит фильтр) следующим образом:

product_groups.first().products.frontend()

Теперь я хочу определить, хочу ли я разместить ссылку на группу продуктовна главной странице, только если в нем четыре или более товаров.
С аннотациями я бы сделал:

product_groups.annotate(num_products=Count('products')).filter(num_products__gte=4)

Но это дает мне причину подсчета все продукты , а не количество продуктов, видимых во внешнем интерфейсе.

Итак, как мне добавить дополнительный фильтр frontend() в мой запрос? Чтобы было ясно, я хочу, чтобы Count() не на 'products', а на products.frontend().

Редактировать:
Это не дубликат предлагаемого вопроса. Если бы функция фильтра frontend() была достаточно простой, чтобы вынуть фильтр и вставить его в агрегатную функцию, предложенный вопрос ответил бы на мою проблему.

Моя frontend() функция довольно сложна и представляет собой совокупность несколькихдругие функции фильтра. Поэтому я действительно хотел бы использовать функцию frontend().

Редактировать:
Это должно работать в Django 1.8.

1 Ответ

1 голос
/ 01 октября 2019

Если вы хотите повторно использовать метод frontend() в Queryset модели Product, то вы можете использовать Subquery агрегатные выражения :

# assumption: `Product` has a fk to `ProductGroup`
# assumption 2: frontend() returns a `Queryset` of `Product` and is a method of `Product` model's default `Queryset`
frontend_products = Product.objects.filter(product_group=OuterRef('pk')).frontend().values('product_group')
total_products = frontend_products.annotate(total=Count('pk')).values('total')
q = product_groups.annotate(num_frontend_products=Subquery(total_products, output_field=IntegerField()))

Обратите внимание, чтоэто заполнит num_frontend_products с None вместо 0 для групп, где нет соответствующего продукта. Возможно, вы захотите изменить набор запросов с помощью условных аннотаций, чтобы заменить None на 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...