Допустим, у меня есть очень простая модель, как этот:Джанго Querysets - Использование .annotate() после .extra()
class Test(models.Model):
category = models.CharField(unique=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
В принципе, я хочу использовать ORM API Django, чтобы получить среднюю продолжительность по категории. Запрос SQL будет выглядеть примерно так:
SELECT category, AVG(end_time - start_time) AS avg_duration
FROM test_table
GROUP BY category
Я попытался, используя следующий код, но в соответствии с Документами, F() выражения в .annotate() доступны только в Djano 1.8.
Test.objects.values('category', 'start_time', 'end_time').annotate(avg_duration=Avg(F(end_time) - F(start_time))
Я также пробовал использовать .extra(), как это, но я получаю FieldError.
Test.objects.extra(select={'duration':'end_time - start_time'}).values('category', 'duration').annotate(avg_duration=Avg('duration'))
С точки зрения вещей, вторая попытка предполагает, что функция аннотации не может разрешать псевдонимы столбцов. Это действительно так, или я что-то упускаю?
Кроме того, кроме создания дополнительного столбца, в котором хранится производная информация (продолжительность для каждой записи), с использованием Django 1.8 и/или с использованием необработанного SQL, какие другие альтернативы вы можете рекомендовать? Любая помощь будет очень оценена. Благодаря!
Я попробовал ваше предложение, а также попробовал это, опасаясь, что требуемые столбцы для .extra() могут не быть обнаружены. 'Test.objects.values ('category', 'end_time', 'start_time').экстра (выберите = { 'avg_duration': 'AVG (END_TIME - start_time)'}) ' Результаты, которые я получил, был похож на основной запрос выбора, как это: ' Выберите категорию, END_TIME, start_time ИЗ test_table' Ницца предложение, но я думаю, что именно поэтому он не сработал: «Любой вызов extra(), сделанный после вызова values (), будет игнорировать его дополнительные выбранные поля». Из [Django docs] (https://docs.djangoproject.com/en/1.7/ref/models/querysets/#values) –
Да, вы правы. Я играл некоторое время, когда оболочка тестировала различные варианты, но не могла найти решение, отличное от '.raw'; ( – Todor
Я очень ценю предложения и усилия! Я буду отмечать это как ответ на благо других, использующих Django 1.7. –