Вы можете использовать агрегатные функции, такие как Count
[Djanog-doc] , Sum
[Django-doc] и т. д. как при вызове функции .annotate(..)
[Django-doc] и .aggregate(..)
.
Но эти два не одинаковы. .aggregate(..)
означает, что мы вычисляем COUNT(*)
, SUM(*)
и т. Д. По всему набору запросов. .aggregate(..)
сделает нетерпеливый вызов базы данных и возвратит словарь, содержащий ключи, которые сопоставляются со значением, полученным из COUNT(*)
и т. Д.
.annotate(..)
с другой стороны, используется для создания агрегатов на объект. Так что он переведет это в запрос с GROUP BY
частью. Это добавит дополнительные атрибуты к объектам модели (или другим объектам), которые возникают из набора запросов. .annotate(..)
создает новый набор запросов, поэтому лениво запрашивает базу данных.
Пример : скажем, у нас есть следующая модель:
class Author(models.Model):
name = models.CharField(max_length=128)
class Book(models.Model):
name = models.CharField(max_length=128)
author = models.ForeignKey(Author, on_delete=models.PROTECT)
Затем мы можем посчитать количество Book
s для всех авторов с именем, которое начинается с 'Alice'
с:
from django.db.models import Count
Author.objects.filter(name__startswith='Alice').aggregate(books=Count('book'))
Здесь мы, таким образом, будем получать словарь, например {'books': 1425}
,содержит общее количество книг, написанных Author
, чье имя начинается с 'Alice'
. Запрос будет выглядеть следующим образом:
SELECT COUNT(book.id) AS books
FROM author
LEFT OUTER JOIN book ON book.author_id = author.id
WHERE author.name LIKE 'Alice%'
Таким образом, мы подсчитываем все книги и получаем один результат.
Однако мы также можем использовать .annotate(..)
:
from django.db.models import Count
Author.objects.filter(name__startswith='Alice').annotate(books=Count('book'))
Это набор запросов, который, в случае оценки, приведет к коллекции Author
с. Каждый Author
, который возникает из этого набора запросов, будет иметь дополнительный атрибут .book
, который содержит количество книг , которые написал автор.
Здесь запрос будеттаким образом выглядят как:
SELECT author.*, COUNT(book.id) AS books
FROM author
LEFT OUTER JOIN book ON book.author_id = author.id
WHERE author.name LIKE 'Alice%'
GROUP BY author.id