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
Here's a simple boiled down failing test case:
diff --git a/tests/queries/tests.py b/tests/queries/tests.py
index 1bd72dd8b8..c6d9b05761 100644
--- a/tests/queries/tests.py
+++ b/tests/queries/tests.py
@@ -1312,6 +1312,10 @@ class Queries1Tests(TestCase):
)
self.assertSequenceEqual(Note.objects.exclude(negate=True), [self.n3])
+ def test_count_on_annotation(self):
+ # Ticket: #34024
+ Tag.objects.annotate(has_pk=~Q(pk=None)).count()
+
class Queries2Tests(TestCase):
@classmethod
results
E
======================================================================
ERROR: test_count_on_annotation (queries.tests.Queries1Tests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/davids/projects/django/tests/queries/tests.py", line 1317, in test_count_on_annotation
Tag.objects.annotate(has_pk=~Q(pk=None)).count()
File "/Users/davids/projects/django/django/db/models/query.py", line 621, in count
return self.query.get_count(using=self.db)
File "/Users/davids/projects/django/django/db/models/sql/query.py", line 554, in get_count
return obj.get_aggregation(using, ["__count"])["__count"]
File "/Users/davids/projects/django/django/db/models/sql/query.py", line 503, in get_aggregation
if expression.is_summary:
AttributeError: 'WhereNode' object has no attribute 'is_summary'
----------------------------------------------------------------------
Ran 1 test in 0.014s
FAILED (errors=1)
Destroying test database for alias 'default'...
Version 0, edited 3 years ago by (next)
comment:5 by , 3 years ago
| Cc: | added |
|---|---|
| Has patch: | set |
| Owner: | changed from to |
| Status: | new → assigned |
Note:
See TracTickets
for help on using tickets.
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'