#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.