#30052 closed Bug (invalid)
QuerySet.only() doesn't support annotations
Reported by: | Kal Sze | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 2.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Example:
from django.db import models class School(models.Model): full_name = models.TextField() class Student(models.Model): full_name = models.TextField() date_of_birth = models.DateField() school = models.ForeignKey(School, on_delete=models.PROTECT)
And then:
from django.db.models import Subquery, OuterRef from schools.models import School, Student eldest_student_name = Student.objects.filter(school=OuterRef('id')).order_by('date_of_birth').values('full_name')[:1] schools = School.objects.annotate(eldest_student_name=Subquery(eldest_student_name)).only('id', 'eldest_student_name') for school in schools: # This line results in FieldDoesNotExist: School has no field named 'eldest_student_name' print(school.id, school.eldest_student_name)
Not sure if this is a bug or an (undocumented) limitation of only()
(and maybe of defer()
, by extension).
Change History (7)
follow-up: 3 comment:1 by , 6 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Summary: | QuerySet's `only()` method does not work with annotated fields → QuerySet.only() doesn't support annotatations |
Type: | Uncategorized → Bug |
comment:2 by , 6 years ago
Summary: | QuerySet.only() doesn't support annotatations → QuerySet.only() doesn't support annotations |
---|
comment:3 by , 6 years ago
Replying to Tim Graham:
As far as I tested, annotations don't need to be included in
only()
in order to be included in the query. The documentation foronly()
anddefer()
only discuss using it with fields, not with annotations.
I know it doesn't need to be included, but I thought the point of only()
and defer()
is to exclude the fields that we are not interested in, when executing the initial database query. Having only()
support annotations is useful if I'm only interested in the annotated field, and not in the regular fields.
EDIT: unless you mean that I can defer the regular fields if I call only()
with no argument at all, and still get the annotated fields immediately?
follow-up: 5 comment:4 by , 6 years ago
I'm not sure. Please test only()
without arguments. If it works, it might be worth adding tests for (if not already in Django's tests) and documenting.
comment:5 by , 6 years ago
Replying to Tim Graham:
I'm not sure. Please test
only()
without arguments. If it works, it might be worth adding tests for (if not already in Django's tests) and documenting.
So I did a quick TIAS and here is what I found out, by printing QuerySet.query
:
QuerySet.only()
without any argument doesn't defer any field; it would select every field of the model plus any annotation added to the QuerySet;QuerySet.only('some_field')
would select theid
,some_field
, plus any annotation added to the QuerySet.
Ideally, it would be great if only()
behaved in one of two ways:
- without any argument, defer all fields except the id and annotations;
or
- accept annotated field names
But it might break old apps and it's too late to change.
As far as I tested, annotations don't need to be included in
only()
in order to be included in the query. The documentation foronly()
anddefer()
only discuss using it with fields, not with annotations.