From eaf9764d3bb25970da89de5799d8d308715628ba Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Tue, 15 Sep 2020 11:40:59 +0200 Subject: [PATCH] Fixed #32007 -- Fixed queryset crash with Q() annotation and aggregation. Thanks Gordon Wrigley for the report. Regression in 8a6df55f2dd5131282084a4edfd48f63fbf8c69a. --- django/db/models/sql/where.py | 3 +++ docs/releases/3.1.2.txt | 3 +++ tests/annotations/tests.py | 11 +++++++++++ 3 files changed, 17 insertions(+) diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py index bf0828dc8b..795eff8395 100644 --- a/django/db/models/sql/where.py +++ b/django/db/models/sql/where.py @@ -159,6 +159,9 @@ class WhereNode(tree.Node): clone.relabel_aliases(change_map) return clone + def copy(self): + return self.clone() + @classmethod def _contains_aggregate(cls, obj): if isinstance(obj, tree.Node): diff --git a/docs/releases/3.1.2.txt b/docs/releases/3.1.2.txt index f9e45370ab..fa820c78ee 100644 --- a/docs/releases/3.1.2.txt +++ b/docs/releases/3.1.2.txt @@ -16,3 +16,6 @@ Bugfixes attribute returned incorrectly ``True`` for ``GROUP BY`` queries (e.g. ``.annotate().values()``) on models with ``Meta.ordering``. A model's ``Meta.ordering`` doesn't affect such queries (:ticket:`31990`). + +* Fixed a regression in Django 3.1 where a queryset would crash if it contained + an aggregation and a ``Q`` object annotation (:ticket:`32007`). diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py index 3d00a02a11..a2bbb95e47 100644 --- a/tests/annotations/tests.py +++ b/tests/annotations/tests.py @@ -183,6 +183,17 @@ class NonAggregateAnnotationTestCase(TestCase): self.assertEqual(book.combined, 13410.0) self.assertEqual(book.rating_count, 1) + def test_q_expression_annotation_with_aggregation(self): + book = Book.objects.filter(isbn='159059725').annotate( + isnull_pubdate=ExpressionWrapper( + Q(pubdate__isnull=True), + output_field=BooleanField(), + ), + rating_count=Count('rating'), + ).first() + self.assertEqual(book.isnull_pubdate, False) + self.assertEqual(book.rating_count, 1) + def test_aggregate_over_annotation(self): agg = Author.objects.annotate(other_age=F('age')).aggregate(otherage_sum=Sum('other_age')) other_agg = Author.objects.aggregate(age_sum=Sum('age'))