summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2020-01-15 09:32:42 +0100
committerGitHub <noreply@github.com>2020-01-15 09:32:42 +0100
commit59b4e99dd00b9c36d56055b889f96885995e4240 (patch)
tree92021fcc157ff675d11bc6d7b9837884609e5e7f
parent63e6ee1f996e16a1a6238fed16fdb28bce156bc6 (diff)
Refs #31136 -- Made QuerySet.values()/values_list() group only by selected annotation.
Regression in 0f843fdd5b9b2f2307148465cd60f4e1b2befbb4.
-rw-r--r--django/db/models/sql/query.py15
-rw-r--r--tests/aggregation/tests.py25
2 files changed, 33 insertions, 7 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index f96a0a6e2d..78c4f47b5b 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -2093,13 +2093,6 @@ class Query(BaseExpression):
self.clear_deferred_loading()
self.clear_select_fields()
- if self.group_by is True:
- self.add_fields((f.attname for f in self.model._meta.concrete_fields), False)
- # Disable GROUP BY aliases to avoid orphaning references to the
- # SELECT clause which is about to be cleared.
- self.set_group_by(allow_aliases=False)
- self.clear_select_fields()
-
if fields:
field_names = []
extra_names = []
@@ -2121,6 +2114,14 @@ class Query(BaseExpression):
self.set_annotation_mask(annotation_names)
else:
field_names = [f.attname for f in self.model._meta.concrete_fields]
+ # Selected annotations must be known before setting the GROUP BY
+ # clause.
+ if self.group_by is True:
+ self.add_fields((f.attname for f in self.model._meta.concrete_fields), False)
+ # Disable GROUP BY aliases to avoid orphaning references to the
+ # SELECT clause which is about to be cleared.
+ self.set_group_by(allow_aliases=False)
+ self.clear_select_fields()
self.values_select = tuple(field_names)
self.add_fields(field_names, True)
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py
index f523b3ca35..06c4cc7ccb 100644
--- a/tests/aggregation/tests.py
+++ b/tests/aggregation/tests.py
@@ -1165,6 +1165,31 @@ class AggregateTestCase(TestCase):
'Sams',
])
+ def test_aggregation_subquery_annotation_values(self):
+ """
+ Subquery annotations and external aliases are excluded from the GROUP
+ BY if they are not selected.
+ """
+ books_qs = Book.objects.annotate(
+ first_author_the_same_age=Subquery(
+ Author.objects.filter(
+ age=OuterRef('contact__friends__age'),
+ ).order_by('age').values('id')[:1],
+ )
+ ).filter(
+ publisher=self.p1,
+ first_author_the_same_age__isnull=False,
+ ).annotate(
+ min_age=Min('contact__friends__age'),
+ ).values('name', 'min_age').order_by('name')
+ self.assertEqual(list(books_qs), [
+ {'name': 'Practical Django Projects', 'min_age': 34},
+ {
+ 'name': 'The Definitive Guide to Django: Web Development Done Right',
+ 'min_age': 29,
+ },
+ ])
+
@skipUnlessDBFeature('supports_subqueries_in_group_by')
def test_group_by_subquery_annotation(self):
"""