summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2022-01-31 11:33:24 +0100
committerGitHub <noreply@github.com>2022-01-31 11:33:24 +0100
commit71e7c8e73712419626f1c2b6ec036e8559a2d667 (patch)
tree0e6b7ad62e5d92b48e4ef3d13103d182d9ad1d22
parentbeb7ddbcee03270e833b2f74927ccfc8027aa693 (diff)
Fixed #33468 -- Fixed QuerySet.aggregate() after annotate() crash on aggregates with default.
Thanks Adam Johnson for the report.
-rw-r--r--django/db/models/aggregates.py4
-rw-r--r--docs/releases/4.0.2.txt4
-rw-r--r--tests/aggregation/tests.py12
3 files changed, 19 insertions, 1 deletions
diff --git a/django/db/models/aggregates.py b/django/db/models/aggregates.py
index 8c4eae7906..bc31b48d8d 100644
--- a/django/db/models/aggregates.py
+++ b/django/db/models/aggregates.py
@@ -65,7 +65,9 @@ class Aggregate(Func):
if hasattr(default, 'resolve_expression'):
default = default.resolve_expression(query, allow_joins, reuse, summarize)
c.default = None # Reset the default argument before wrapping.
- return Coalesce(c, default, output_field=c._output_field_or_none)
+ coalesce = Coalesce(c, default, output_field=c._output_field_or_none)
+ coalesce.is_summary = c.is_summary
+ return coalesce
@property
def default_alias(self):
diff --git a/docs/releases/4.0.2.txt b/docs/releases/4.0.2.txt
index c60dc68224..e7b9879625 100644
--- a/docs/releases/4.0.2.txt
+++ b/docs/releases/4.0.2.txt
@@ -33,3 +33,7 @@ Bugfixes
* Fixed a duplicate operation regression in Django 4.0 that caused a migration
crash when altering a primary key type for a concrete parent model referenced
by a foreign key (:ticket:`33462`).
+
+* Fixed a bug in Django 4.0 that caused a crash of ``QuerySet.aggregate()``
+ after ``annotate()`` on an aggregate function with a
+ :ref:`default <aggregate-default>` (:ticket:`33468`).
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py
index 87ae945a7e..5c9aa5d534 100644
--- a/tests/aggregation/tests.py
+++ b/tests/aggregation/tests.py
@@ -1630,6 +1630,18 @@ class AggregateTestCase(TestCase):
)
self.assertAlmostEqual(result['value'], Decimal('61.72'), places=2)
+ def test_aggregation_default_after_annotation(self):
+ result = Publisher.objects.annotate(
+ double_num_awards=F('num_awards') * 2,
+ ).aggregate(value=Sum('double_num_awards', default=0))
+ self.assertEqual(result['value'], 40)
+
+ def test_aggregation_default_not_in_aggregate(self):
+ result = Publisher.objects.annotate(
+ avg_rating=Avg('book__rating', default=2.5),
+ ).aggregate(Sum('num_awards'))
+ self.assertEqual(result['num_awards__sum'], 20)
+
def test_exists_none_with_aggregate(self):
qs = Book.objects.all().annotate(
count=Count('id'),