Джанго: Группировать по? - PullRequest
3 голосов
/ 13 марта 2010

Я ищу что-то вроде следующего:

previous_invoices = Invoice.objects.filter(is_open=False)
                                   .order_by('-created')
                                   .group_by('user')

, но group_by() не существует ...

Это найдет последний закрытый счет для каждого пользователя,

Этот API агрегирования , кажется, позволяет вам делать подобные вещи для подсчетов и сумм, но мне не нужен подсчет, или сумма, или что-то еще, я действительно хочу объекты счета!

Ответы [ 2 ]

2 голосов
/ 13 марта 2010

Есть эта страница из 2007 , которая взломала ее на django, но это было бы спорным, так как до версии 1.1 в любом случае недокументированное group_by` Но эта ветка годичной давности , похоже, обладает некоторой проницательностью. По существу:

Django преднамеренно не раскрывает «GROUP BY» или что-либо подобное в ОРМ. Хотя тот факт, что мы через реляционный сервер хранения иногда просачивается через API ORM является довольно независимым от SQL. Вместо этого мы выставлять конкретные кусочки функциональность, которая случается реализовано с использованием «GROUP BY», когда это превратился в SQL (и вполне может быть реализуется некоторыми совершенно разными набор волшебных фей с бэкэнд другой системы хранения).

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

1 голос
/ 07 августа 2017

Вариант 1:

Хотя group_by() не существует в Django, вы можете попытаться найти последний закрытый счет для каждого пользователя, используя метод и фильтр latest() для пользователя:

previous_invoices = Invoice.objects.filter(user=my_user, is_open=False)
                                   .latest('created') 

Для более старых версий Django, где latest() не существует, запрос будет выглядеть следующим образом:

previous_invoices = Invoice.objects.filter(user=my_user, is_open=False)
                                   .order_by('-created')[0]

Вариант 2:

Если вы абсолютно хотите создать эффекты group_by, создайте их вручную, как показано в принятом ответе здесь: Значение поля Django GROUP BY .

  1. Используйте .values_list() с flat=True, чтобы получить список существующих значений в вашей базе данных (если вы не знаете их заранее). Также используйте .distinct(), чтобы исключить дублирующиеся значения, так как мы не заботимся о них:

    value_list = MyModel.objects.values_list(
        'interesting_field', flat=True
    ).distinct()
    
  2. Теперь переберите value_list и заполните свой словарь:

    group_by_value = {}
    for value in value_list:
        group_by_value[value] = MyModel.objects.filter(interesting_field=value)
    

Теперь group_by_value словарь содержит в качестве ключей различные значения в вашем interesting_field и в качестве значений объектов набора запросов, каждый содержащие записи MyModel с interesting_field=a value from value_list.


Примечание:

Существует такая библиотека django-group-by , которая утверждает, что добавила group_by() в Django, который вы можете захотеть проверить.

...