Opened 50 minutes ago
Last modified 48 minutes ago
#37308 new Cleanup/optimization
Lookups on annotation aliases in .values() and .order_by() resolve unexpectedly
| Reported by: | Annabelle Wiegart | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 6.1 |
| Severity: | Normal | Keywords: | alias, values, order_by |
| Cc: | Annabelle Wiegart | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Doing a lookup on an annotation alias results in an unexpected name resolution. When calling e.g. .values(alias + "__pk"), Query.names_to_path() checks if f"{alias}__pk" is the name of an annotation. Otherwise it tries to resolve the name into field plus lookup. This might be unexpected. While allowing lookups on aliases may add too much complexity and therefore not be desirable, it would probably be helpful to at least show a warning when .values() or .order_by() is called on an expression containing an alias name and __.
The issue has been discussed in PR21803 for #36945.
Reproducer:
from django.db import models from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType class Person(models.Model): name = models.CharField(max_length=100) creator = models.ForeignKey(User, models.CASCADE, null=True) ct = models.ForeignKey(ContentType, models.CASCADE) def run(): admin = User.objects.create(username='admin') person_ct = ContentType.objects.get_for_model(Person) Person.objects.create(creator=admin, name="Claude", ct=person_ct) # resolves correctly qs1 = Person.objects.all().values("creator__pk") print(qs1) alias = "myalias" # raises FieldError qs2 = Person.objects.annotate(**{alias: models.F("creator")}).values(alias + "__pk") print(qs2) # raises FieldError qs3 = Person.objects.annotate( **{alias: models.FilteredRelation("creator", condition=models.Q(creator__isnull=False))} ).values(alias + "__pk") print(qs3)
Output:
django.core.exceptions.FieldError: Cannot resolve keyword 'myalias' into field. Choices are: creator, creator_id, ct, ct_id, id, name