Opened 3 hours ago

Last modified 13 minutes ago

#37274 assigned Bug

Transforms in order_by() not allowed after alias()

Reported by: Jacob Walls Owned by: Jacob Walls
Component: Database layer (models, ORM) Version: 6.1
Severity: Normal Keywords:
Cc: Pravin Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

This example fails with:

django.core.exceptions.FieldError: Cannot resolve keyword 'other_pubdate' into field. Choices are: ... other_pubdate, ...
  • tests/annotations/tests.py

    diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
    index 42fccca7d6..4baef9e463 100644
    a b class AliasTests(TestCase):  
    14811481        self.assertIs(hasattr(qs.first(), "other_age"), False)
    14821482        self.assertQuerySetEqual(qs, [34, 34, 35, 46, 57], lambda a: a.age)
    14831483
     1484    def test_order_by_alias_transform(self):
     1485        qs = (
     1486            Book.objects.alias(other_pubdate=F("pubdate"))
     1487            .order_by("-other_pubdate__year")
     1488        )
     1489        self.assertQuerySetEqual(qs, [2008, 2007, 1995, 1991], lambda a: a.pubdate.year)
     1490
    14841491    def test_order_by_alias_aggregate(self):
    14851492        qs = (
    14861493            Author.objects.values("age")

However, all of these variants work, suggesting to me that there should be a simple fix.

Keep the transform, change alias to annotate:

Book.objects.annotate(other_pubdate=F("pubdate")).order_by("other_pubdate__year")

Keep the transform, use a field name:

Book.objects.order_by("pubdate__year")

Keep the alias, drop the transform:

Book.objects.alias(other_pubdate=F("pubdate")).order_by("other_pubdate")

If not practical for some reason, then at the very least we should improve "Cannot resolve keyword 'other_pubdate' into field. Choices are: ... other_pubdate, ...".

Change History (2)

comment:1 by Pravin, 3 hours ago

The simple fix i could see around https://github.com/django/django/blob/c6be0bf3bb744d234947cefd6def9f31d9655800/django/db/models/sql/query.py#L2342
for example,

diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index adf0663beb..91d3436cf0 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -2339,7 +2339,7 @@ class Query(BaseExpression):
                 if item == "?":
                     continue
                 item = item.removeprefix("-")
-                if item in self.annotations:
+                if item in self.annotations or self.annotations.get(item.split(LOOKUP_SEP)[0]):
                     continue
                 if self.extra and item in self.extra:
                     continue

But this may introduce edge around bad aliases , it will failed if there is __ in the alias, as we have already discussed similar in Multi-column subquery work

Version 1, edited 3 hours ago by Pravin (previous) (next) (diff)

comment:2 by Jacob Walls, 13 minutes ago

Has patch: set
Owner: set to Jacob Walls
Status: newassigned
Note: See TracTickets for help on using tickets.
Back to Top