summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHasan Ramezani <hasan.r67@gmail.com>2020-11-17 23:31:58 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-11-19 21:42:14 +0100
commit166c0d2474a3b5e09e1dd96ec93bdbf08f0c65c2 (patch)
treef227610b6fb9658dde3a5d0ae04680949b24368c
parent012822c7f9eb2be2f44cb3235eb66ca207d37133 (diff)
[3.1.x] Fixed #32200 -- Fixed grouping by ExpressionWrapper() with Q objects.
Thanks Gordon Wrigley for the report. Regression in df32fd42b84cc6dbba173201f244491b0d154a63. Backport of fe9c7ded2996364f853c524b4421274717d89d5f from master
-rw-r--r--django/db/models/expressions.py10
-rw-r--r--docs/releases/3.1.4.txt3
-rw-r--r--tests/annotations/tests.py12
3 files changed, 22 insertions, 3 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 61bdfba2f2..b5668b685e 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -866,9 +866,13 @@ class ExpressionWrapper(Expression):
return [self.expression]
def get_group_by_cols(self, alias=None):
- expression = self.expression.copy()
- expression.output_field = self.output_field
- return expression.get_group_by_cols(alias=alias)
+ if isinstance(self.expression, Expression):
+ expression = self.expression.copy()
+ expression.output_field = self.output_field
+ return expression.get_group_by_cols(alias=alias)
+ # For non-expressions e.g. an SQL WHERE clause, the entire
+ # `expression` must be included in the GROUP BY clause.
+ return super().get_group_by_cols()
def as_sql(self, compiler, connection):
return compiler.compile(self.expression)
diff --git a/docs/releases/3.1.4.txt b/docs/releases/3.1.4.txt
index ca75d303b9..4d9e949791 100644
--- a/docs/releases/3.1.4.txt
+++ b/docs/releases/3.1.4.txt
@@ -21,3 +21,6 @@ Bugfixes
* Fixed a regression in Django 3.1 that caused a crash of auto-reloader for
certain invocations of ``runserver`` on Windows with Python 3.7 and below
(:ticket:`32202`).
+
+* Fixed a regression in Django 3.1 that caused the incorrect grouping by a
+ ``Q`` object annotation (:ticket:`32200`).
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index 06038781f2..8459a0ae8e 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -199,6 +199,18 @@ class NonAggregateAnnotationTestCase(TestCase):
self.assertEqual(book.isnull_pubdate, False)
self.assertEqual(book.rating_count, 1)
+ @skipUnlessDBFeature('supports_boolean_expr_in_select_clause')
+ def test_grouping_by_q_expression_annotation(self):
+ authors = Author.objects.annotate(
+ under_40=ExpressionWrapper(Q(age__lt=40), output_field=BooleanField()),
+ ).values('under_40').annotate(
+ count_id=Count('id'),
+ ).values('under_40', 'count_id')
+ self.assertCountEqual(authors, [
+ {'under_40': False, 'count_id': 3},
+ {'under_40': True, 'count_id': 6},
+ ])
+
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'))