Можем ли мы использовать django orm, чтобы получить вывод, как показано ниже - PullRequest
0 голосов
/ 06 июня 2018
[
    {'month_number':[1,2,3,4,5]},
    {'month_number_2':[6,6,8,8,8,10]}
]

class Test(Modelbase):
    student_id = models.IntegerField(null=True)

Выше приведена модель, а поля по умолчанию - selected_at, чтобы получить число_месяца.

Я использовал приведенный ниже запрос для фильтрации данных, но с помощью этого нам придется повторить цикл, чтобы различать разныемесяц.

Model.objects.filter(created_at__month__gte=3).values(*['student_id','created_at'])

Можем ли мы сделать это, используя Django ORM за один раз?

1 Ответ

0 голосов
/ 06 июня 2018

Вы можете использовать groupby itertools:

<b>from django.db.models import F, Func
from itertools import groupby
from operator import itemgetter</b>

query = (Model.objects<b>.annotate(month=Func(F('created_at'), function='MONTH'))</b>
                      .filter(month__gte=3)
                      <b>.order_by('month')</b>
                      .values('student_id','month'))

result = {
    m: [x['student_id'] for x in xs]
    for m, xs in <b>groupby(query, itemgetter('month'))</b>
}

Таким образом, мы сначала генерируем запрос, в котором мы создаем аннотацию: мы аннотируем каждый экземпляр Model с атрибутом month, который являетсямесяц поля created_at.

Далее мы фильтруем на основе того факта, что этот столбец month больше или равен 3, затем мы упорядочиваем набор запросов по этому month (этоважно для функции groupby, которая работает только в том случае, если элементы формируют группы на основе элемента, который мы хотим сгруппировать. Затем мы выполняем values(..), чтобы сделать запрос более эффективным.

Затем выполняем groupby(query, itemgetter('month')) поэтому мы создаем куски элементов с одним и тем же месяцем. Это создает итерацию из 2 кортежей с m номером месяца и xs итерируемым из словарей, принадлежащих этой группе.

Мыпреобразовать эту итерацию таким образом в словарь, где m отображается в список student_id s.

...