[Django] #37330: Transform on an annotation alias crashes when output_field is not attached to a model

11 views
Skip to first unread message

Django

unread,
Sep 7, 2026, 12:44:51 PMSep 7
to django-...@googlegroups.com
#37330: Transform on an annotation alias crashes when output_field is not attached
to a model
-----------------------------------------+--------------------------
Reporter: Kunal Kumar | Owner: (none)
Type: Bug | Status: assigned
Component: Uncategorized | Version: dev
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 1
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+--------------------------
Applying a transform to an annotation alias raises AttributeError when the
annotation's output_field is not attached to a model:

{{{#!python
Book.objects.annotate(
published=ExpressionWrapper(F("pubdate"), output_field=DateField())
).values("published__year")
}}}

{{{
AttributeError: 'DateField' object has no attribute 'model'
}}}

Value(..., output_field=DateField()) fails the same way.

The same query works when the annotation's output_field happens to be a
model
field, so the outcome depends on how the annotation was spelled rather
than on
what it asks for:

|| annotation || .values("a__year") ||
|| annotate(a=F("pubdate")) || works ||
|| annotate(a=ExpressionWrapper(F("pubdate"), output_field=DateField()))
|| AttributeError ||
|| annotate(a=Value(date(2026, 1, 1), output_field=DateField())) ||
AttributeError ||

Cause: names_to_path() resolves an annotation name to
self.annotations[name].output_field, which annotate() does not require to
be
attached to a model. setup_joins()'s final_transformer() then calls
field.get_col(alias), and Field.get_col() dereferences self.model.

names_to_path() already anticipates this a few lines earlier:

{{{#!python
try:
model = field.model._meta.concrete_model
except AttributeError:
# QuerySet.annotate() may introduce fields that aren't attached to a
model.
model = None
}}}

An AttributeError escaping here also bypasses add_fields(), which catches
FieldError to build a helpful message.

Closest precedent found: #34921, same class of failure (an unsuccessful
self.model access on an unbound field, there in
DateTimeField.to_python()).
I also searched for "unbound annotation", "output_field model attribute"
and
"has no attribute model"; #36787 and #37248 are the nearest hits and
neither
covers this path — both are closed/fixed with different symptoms.

Patch: https://github.com/django/django/pull/21914
--
Ticket URL: <https://code.djangoproject.com/ticket/37330>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Sep 7, 2026, 2:23:54 PMSep 7
to django-...@googlegroups.com
#37330: Transform on an annotation alias crashes when output_field is not attached
to a model
-------------------------------------+-------------------------------------
Reporter: Kunal Kumar | Owner: Kunal
| Kumar
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Kunal Kumar):

* component: Uncategorized => Database layer (models, ORM)
* owner: (none) => Kunal Kumar

--
Ticket URL: <https://code.djangoproject.com/ticket/37330#comment:1>

Django

unread,
Sep 11, 2026, 8:55:23 AMSep 11
to django-...@googlegroups.com
#37330: Transform on an annotation alias crashes when output_field is not attached
to a model
-------------------------------------+-------------------------------------
Reporter: Kunal Kumar | Owner: Kunal
| Kumar
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Sarah Boyce):

* stage: Unreviewed => Accepted

Comment:

Replicated, thank you for the report
--
Ticket URL: <https://code.djangoproject.com/ticket/37330#comment:2>

Django

unread,
Sep 11, 2026, 8:57:02 AMSep 11
to django-...@googlegroups.com
#37330: Transform on an annotation alias crashes when output_field is not attached
to a model
-------------------------------------+-------------------------------------
Reporter: Kunal Kumar | Owner: Kunal
| Kumar
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Sarah Boyce):

* needs_better_patch: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/37330#comment:3>

Django

unread,
Sep 25, 2026, 4:43:22 PM (yesterday) Sep 25
to django-...@googlegroups.com
#37330: Transform on an annotation alias crashes when output_field is not attached
to a model
-------------------------------------+-------------------------------------
Reporter: Kunal Kumar | Owner: Kunal
| Kumar
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by David Smith):

* cc: Jacob Walls (added)
* severity: Normal => Release blocker

Comment:

> The same query works when the annotation's output_field happens to be a
model field

While it doesn't crash, the output seems incorrect to me.

Here is a test to add to `tests/annotations/tests.py`

{{{
@register_lookup(CharField, Length)
def test_values_transform_on_annotation_of_related_field(self):
# Book and Publisher both have a "name" column.
qs = Book.objects.annotate(publisher_name=F("publisher__name"))
self.assertEqual(
qs.values_list("publisher_name__length",
flat=True).get(pk=self.b1.pk),
len(self.p1.name),
)
}}}

This fails with

{{{
AssertionError: 58 != 6
}}}

The query returned the length of the book name rather than the publisher
name.

I bisected the change to be6cf832293779d8aeaeddca8c47a37ba1530898. Before
this change it crashed with `FieldError` but now returns a value which I
believe to be incorrect. I think the severity of this should be increased
to a release blocker.
--
Ticket URL: <https://code.djangoproject.com/ticket/37330#comment:4>
Reply all
Reply to author
Forward
0 new messages