summaryrefslogtreecommitdiff
path: root/docs/topics
diff options
context:
space:
mode:
authorTom <tom@tomforb.es>2017-04-22 16:44:51 +0100
committerTim Graham <timograham@gmail.com>2017-08-12 17:58:28 -0400
commitb78d100fa62cd4fbbc70f2bae77c192cb36c1ccd (patch)
treebe1f272298c15c6a261e33dff7486b0c3727b407 /docs/topics
parent489421b01562494ab506de5d30ea97d7b6b5df30 (diff)
Fixed #27849 -- Added filtering support to aggregates.
Diffstat (limited to 'docs/topics')
-rw-r--r--docs/topics/db/aggregation.txt33
1 files changed, 33 insertions, 0 deletions
diff --git a/docs/topics/db/aggregation.txt b/docs/topics/db/aggregation.txt
index 1f59c02b4d..523f6e0aaa 100644
--- a/docs/topics/db/aggregation.txt
+++ b/docs/topics/db/aggregation.txt
@@ -84,6 +84,16 @@ In a hurry? Here's how to do common aggregate queries, assuming the models above
>>> pubs[0].num_books
73
+ # Each publisher, with a separate count of books with a rating above and below 5
+ >>> from django.db.models import Q
+ >>> above_5 = Count('book', filter=Q(book__rating__gt=5))
+ >>> below_5 = Count('book', filter=Q(book__rating__lte=5))
+ >>> pubs = Publisher.objects.annotate(below_5=below_5).annotate(above_5=above_5)
+ >>> pubs[0].above_5
+ 23
+ >>> pubs[0].below_5
+ 12
+
# The top 5 publishers, in order by number of books.
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
@@ -324,6 +334,8 @@ title that starts with "Django" using the query::
>>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price'))
+.. _filtering-on-annotations:
+
Filtering on annotations
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -339,6 +351,27 @@ you can issue the query::
This query generates an annotated result set, and then generates a filter
based upon that annotation.
+If you need two annotations with two separate filters you can use the
+``filter`` argument with any aggregate. For example, to generate a list of
+authors with a count of highly rated books::
+
+ >>> highly_rated = Count('books', filter=Q(books__rating__gte=7))
+ >>> Author.objects.annotate(num_books=Count('books'), highly_rated_books=highly_rated)
+
+Each ``Author`` in the result set will have the ``num_books`` and
+``highly_rated_books`` attributes.
+
+.. admonition:: Choosing between ``filter`` and ``QuerySet.filter()``
+
+ Avoid using the ``filter`` argument with a single annotation or
+ aggregation. It's more efficient to use ``QuerySet.filter()`` to exclude
+ rows. The aggregation ``filter`` argument is only useful when using two or
+ more aggregations over the same relations with different conditionals.
+
+.. versionchanged:: 2.0
+
+ The ``filter`` argument was added to aggregates.
+
Order of ``annotate()`` and ``filter()`` clauses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~