From 4bd55547214ae149acadffe60536c379d51e318f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anssi=20K=C3=A4=C3=A4ri=C3=A4inen?= Date: Tue, 23 Jul 2013 11:38:38 +0300 Subject: [PATCH] Fixed #20782 -- qs.values().aggregate() failure In the combination of .values().aggregate() the aggregate_select_mask didn't include the aggregates added. This resulted in bogus query. Thanks to Trac alias debanshuk for report. --- django/db/models/query.py | 5 ++++- django/db/models/sql/query.py | 4 ++++ tests/aggregation/tests.py | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/django/db/models/query.py b/django/db/models/query.py index 811e917764..9dcf620448 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -274,9 +274,12 @@ class QuerySet(object): query = self.query.clone() + aggregate_names = [] for (alias, aggregate_expr) in kwargs.items(): query.add_aggregate(aggregate_expr, self.model, alias, - is_summary=True) + is_summary=True) + aggregate_names.append(alias) + query.append_aggregate_mask(aggregate_names) return query.get_aggregation(using=self.db) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 2a9b8ef826..da0c39e1e7 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1753,6 +1753,10 @@ class Query(object): self.aggregate_select_mask = set(names) self._aggregate_select_cache = None + def append_aggregate_mask(self, names): + if self.aggregate_select_mask is not None: + self.set_aggregate_mask(set(names).union(self.aggregate_select_mask)) + def set_extra_mask(self, names): """ Set the mask of extra select items that will be returned by SELECT, diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py index c635e6ebb6..dd7e994a63 100644 --- a/tests/aggregation/tests.py +++ b/tests/aggregation/tests.py @@ -585,3 +585,14 @@ class BaseAggregateTestCase(TestCase): "datetime.date(2008, 1, 1)" ] ) + + def test_values_aggregation(self): + # Refs #20782 + max_rating = Book.objects.values('rating').aggregate(max_rating=Max('rating')) + self.assertEqual(max_rating['max_rating'], 5) + max_books_per_rating = Book.objects.values('rating').annotate( + books_per_rating=Count('id') + ).aggregate(Max('books_per_rating')) + self.assertEqual( + max_books_per_rating, + {'books_per_rating__max': 3})