Группировка запросов по дате - PullRequest
0 голосов
/ 30 октября 2018

У меня есть класс, который содержит дату, а также некоторые другие поля.

То, что я пытаюсь выяснить, это запрос, который вернет мне каждый из элементов, сгруппированных по дате.

Итак, учитывая следующий класс: -

class Item(models.Model):
    item_date = models.DateField()
    <other fields>

Я бы хотел получить что-то вроде этого: -

[
    {
        'item_date': datetime.date(2018, 9, 12),
        'items': <Queryset [<Item: item1>, <Item: item17> ...]
    }, {
        'item_date': datetime.date(2018, 9, 13),
        'items': <Queryset [<Item: item2>, <Item: item33> ...]
    }, {
        'item_date': datetime.date(2018, 9, 14),
        'items': <Queryset [<Item: item34>, <Item: item37> ...]
    } ...
]

Я почти уверен, что мне нужна какая-то аннотация, но я не уверен на 100%, как ее структурировать.

Самое близкое, что у меня есть: -

Item.objects.values('item_date').annotate(Count('id')).order_by('item_date')

но это просто дает мне счет того, сколько предметов на каждую дату, а не фактических предметов (очевидно!).

Что мне нужно вместо этого графа? Это вообще возможно?!

1 Ответ

0 голосов
/ 30 октября 2018

Большинство (если не все) SQL баз данных не могут возвращать иерархических данных, или, по крайней мере, без большого количества уловок. Вы должны сделать упорядочивание на уровне Django, например, с itertools.groupby [Python-doc] :

from itertools import groupby
from operator import attrgetter

result = [
    {'item_date': k, 'items': list(vs)}
    for k, vs in groupby(
        Item.objects.all().order_by('item_date'),
        attrgetter('item_date')
    )
]

Как правило, накладные расходы не будут такими значительными, поскольку десериализация объектов уже занимает линейное время, а это itertools.groupby также требует линейного времени.

Важно .order_by(..) ключевая функция, поскольку .groupby(..) сначала не просматривает все объекты перед группировкой: она группирует «подпоследовательности» элементов с одинаковым значением ключа.

...