diff options
| author | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-01-15 09:32:42 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-01-15 09:33:36 +0100 |
| commit | a24686987f21fe6b5339cc13607c13fa906f81a8 (patch) | |
| tree | 0fea2987450e04b3fa0098db8beccc9987e1d494 | |
| parent | 6aac9f6b1148bdc24dd282b9932c1ae55b489724 (diff) | |
[3.0.x] Refs #31136 -- Made QuerySet.values()/values_list() group only by selected annotation.
Regression in 0f843fdd5b9b2f2307148465cd60f4e1b2befbb4.
Backport of 59b4e99dd00b9c36d56055b889f96885995e4240 from master
| -rw-r--r-- | django/db/models/sql/query.py | 15 | ||||
| -rw-r--r-- | tests/aggregation/tests.py | 25 |
2 files changed, 33 insertions, 7 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index c5a42b2b67..fc1b916812 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -2098,13 +2098,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 = [] @@ -2126,6 +2119,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 2cabeb5df8..bef415abd4 100644 --- a/tests/aggregation/tests.py +++ b/tests/aggregation/tests.py @@ -1163,6 +1163,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): """ |
