Opened 3 years ago
Closed 3 years ago
#34024 closed Bug (fixed)
'WhereNode' object has no attribute 'is_summary' when counting a queryset with annotation from a subquery
| Reported by: | Valentin Rigal | Owned by: | David Sanders |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 4.1 |
| Severity: | Normal | Keywords: | |
| Cc: | David Sanders, David Wobrock | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I reproduced on a blank project (4.0 and 4.1 with a Postgres database) using this use case:
models.py
class School(models.Model):
"""A school"""
class Director(models.Model):
school = models.ForeignKey(School, on_delete=models.CASCADE)
speciality = models.CharField(max_length=200)
It is not possible to run this code:
>>> School.objects.annotate( >>> speciality=Subquery(Director.objects.values('speciality')[:1]), >>> has_speciality=Q(speciality__isnull=False) >>> ).count() … AttributeError: 'WhereNode' object has no attribute 'is_summary'
Reverting this precise commit seems to fix the issue : https://github.com/django/django/commit/b64db05b9cedd96905d637a2d824cbbf428e40e7
The request is a bit exotic, I don't know if it should be supported.
This is the first ticket I open, I can clarify/submit a merge request if needed.
Change History (6)
comment:1 by , 3 years ago
comment:2 by , 3 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:3 by , 3 years ago
| Cc: | added |
|---|
comment:4 by , 3 years ago
FYI: none of the original tests from the PR introducing WhereNode.is_summary were testing with Q
Here's a simplified failing test case to go alongside those added with the PR:
diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py
index e15e7e41d9..cc92029135 100644
--- a/tests/aggregation_regress/tests.py
+++ b/tests/aggregation_regress/tests.py
@@ -554,6 +554,10 @@ class AggregationTests(TestCase):
325,
)
+ def test_q_annotation_aggregate(self):
+ # Ensure aggregation works with annotations using Q objects
+ Book.objects.annotate(has_pk=~Q(pk=None)).count()
+
def test_decimal_aggregate_annotation_filter(self):
"""
Filtering on an aggregate annotation with Decimal values should work.
comment:5 by , 3 years ago
| Cc: | added |
|---|---|
| Has patch: | set |
| Owner: | changed from to |
| Status: | new → assigned |
Confirmed on latest main.
Full traceback from ipython:
[ins] In [1]: School.objects.annotate( ...: speciality=Subquery(Director.objects.values('speciality')[:1]), ...: has_speciality=Q(speciality__isnull=False) ...: ).count() --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In [1], line 4 1 School.objects.annotate( 2 speciality=Subquery(Director.objects.values('speciality')[:1]), 3 has_speciality=Q(speciality__isnull=False) ----> 4 ).count() File ~/projects/django/django/db/models/query.py:621, in QuerySet.count(self) 618 if self._result_cache is not None: 619 return len(self._result_cache) --> 621 return self.query.get_count(using=self.db) File ~/projects/django/django/db/models/sql/query.py:554, in Query.get_count(self, using) 552 obj = self.clone() 553 obj.add_annotation(Count("*"), alias="__count", is_summary=True) --> 554 return obj.get_aggregation(using, ["__count"])["__count"] File ~/projects/django/django/db/models/sql/query.py:503, in Query.get_aggregation(self, using, added_aggregate_names) 501 for alias, expression in list(inner_query.annotation_select.items()): 502 annotation_select_mask = inner_query.annotation_select_mask --> 503 if expression.is_summary: 504 expression, col_cnt = inner_query.rewrite_cols(expression, col_cnt) 505 outer_query.annotations[alias] = expression.relabeled_clone( 506 relabels 507 ) AttributeError: 'WhereNode' object has no attribute 'is_summary'