Есть ли способ объединить аннотации и отфильтрованные агрегаты в Django Querysets? - PullRequest
0 голосов
/ 28 мая 2019

У меня сложный запрос, который, хотя он легко выполняется в коде Python, я пытаюсь выполнить с помощью Django Querysets.

Используя примеры моделей из https://docs.djangoproject.com/en/2.2/topics/db/aggregation/#aggregating-annotations,, я пытаюсь аннотировать каждого издателя средним значением общих продаж на автора.Однако общий объем продаж на одного автора должен включать в себя только книги с заданным диапазоном дат.

Есть ли способ сделать это в одном запросе?Конечно, можно сделать два отдельных запроса и объединить результаты, используя чистый Python.Тем не менее, в моем конкретном случае использования существует большое количество накладных расходов для каждого подключения / отключения базы данных, поэтому было бы предпочтительно объединить их в один запрос.Кроме того, реальный набор данных довольно велик, поэтому очень важно выполнить агрегирование на стороне сервера.

Вот пример вывода json, который я ожидал бы:

{ "publishers": [{ "name": "testpublisher", "avg_recent_sales": "11.2" }, { "name": "anotherpublisher", "avg_recent_sales": "2.4" }] }

Где avg_recent_sales - это среднее количество книг, проданных каждым автором через этого издателя за последние 6 месяцев.

1 Ответ

0 голосов
/ 28 мая 2019

Набор запросов Django ленив. Вы можете фильтровать или аннотировать столько раз, сколько захотите, пока не выполните итерацию (например, поместите его в «for» или преобразуйте в «список»)

Я добавил "sold_amount" в модель Book.

books = Book.objects.filter(pubdate__range=(date1, date2))  # filter by given date range.
books = books.values('publisher__id', 'authors__id')  # create group by clause.
books = books.annotate(total_sale_per_author=Avg(F('sold_amount') * F('price')))  # add an annotation.

books = list(book)  # query will be occured here
...