Возврат объекта при агрегировании сгруппированных полей в Django - PullRequest
0 голосов
/ 10 июня 2018

Предполагая следующую модель примера:

# models.py
class event(models.Model):
    location = models.CharField(max_length=10)
    type = models.CharField(max_length=10)
    date = models.DateTimeField()
    attendance = models.IntegerField()

Я хочу получить номер посещаемости для последней даты каждого местоположения события и комбинации типов, используя Django ORM.Согласно документации Django Aggregation , мы можем достичь чего-то близкого к этому, используя values перед annotation.

... исходные результаты сгруппированы в соответствии суникальные комбинации полей, указанных в предложении values ​​().Затем предоставляется аннотация для каждой уникальной группы;аннотация вычисляется для всех членов группы.

Таким образом, используя примерную модель, мы можем написать:

event.objects.values('location', 'type').annotate(latest_date=Max('date'))

, которая действительно группирует события по местоположению и типу, но не возвращает поле attendance , которое является желаемым поведением.

Еще один подход, который я пробовал, состоял в том, чтобы использовать разные, то есть:

event.objects.distinct('location', 'type').annotate(latest_date=Max('date'))

, но я получаюошибка

NotImplementedError: annotate() + distinct(fields) is not implemented.

Я нашел несколько ответов, которые основаны на специфических особенностях базы данных Django, но я хотел бы найти решение, которое не зависит от базовой реляционной базы данных.

1 Ответ

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

Хорошо, я думаю, что этот может действительно работать для вас.Он основан на предположении, которое я считаю правильным.

Когда вы создаете объект модели, все они должны быть уникальными.Очень маловероятно, что у вас будет два event на одном и том же date, на одном и том же location на одном и том же type.Итак, с этим предположением, давайте начнем: (как примечание форматирования, класс Names имеет тенденцию начинаться с заглавных букв, чтобы различать classes и variables или instances.)

# First you get your desired events with your criteria.
results = Event.objects.values('location', 'type').annotate(latest_date=Max('date'))

# Make an empty 'list' to store the values you want.
results_list = []

# Then iterate through your 'results' looking up objects
# you want and populating the list.
for r in results:
    result = Event.objects.get(location=r['location'], type=r['type'], date=r['latest_date'])
    results_list.append(result)

# Now you have a list of objects that you can do whatever you want with.

Вывозможно, придется искать точный вывод Max(Date), но это должно привести вас на правильный путь.

...