#36480: FieldError when referencing a nonexistent alias provides less 
information
than nonexistent annotation
-------------------------------------+-------------------------------------
     Reporter:  Jacob Walls          |                     Type:
                                     |  Cleanup/optimization
       Status:  new                  |                Component:  Database
                                     |  layer (models, ORM)
      Version:  dev                  |                 Severity:  Normal
     Keywords:  typo                 |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  1                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
 When migrating some querysets to use `.alias()` rather than `.annotate()`
 for
 
[https://docs.djangoproject.com/en/5.2/ref/models/querysets/#django.db.models.query.QuerySet.alias
 performance purposes], I noticed when you typo a reference to an argument
 to `.alias()`, the hint provided by the `FieldError` does not include it.

 (Whereas when using `.annotate()`, the `FieldError` hint ''does'' include
 what you meant.)

 {{{#!py
 In [1]: from django.db.models import F
 In [2]: Tile.objects.alias(my_alias=F("pk")).order_by("typo")  # notice
 "my_alias" missing from hint
 ---------------------------------------------------------------------------
 FieldError                                Traceback (most recent call
 last)
 Cell In[2], line 1
 ----> 1 Tile.objects.alias(my_alias=F("pk")).order_by("typo")

 File ~/py313/lib/python3.13/site-packages/django/db/models/query.py:1722,
 in QuerySet.order_by(self, *field_names)
    1720 obj = self._chain()
    1721 obj.query.clear_ordering(force=True, clear_default=False)
 -> 1722 obj.query.add_ordering(*field_names)
    1723 return obj

 File ~/py313/lib/python3.13/site-
 packages/django/db/models/sql/query.py:2291, in Query.add_ordering(self,
 *ordering)
    2288         continue
    2289     # names_to_path() validates the lookup. A descriptive
    2290     # FieldError will be raise if it's not.
 -> 2291     self.names_to_path(item.split(LOOKUP_SEP), self.model._meta)
    2292 elif not hasattr(item, "resolve_expression"):
    2293     errors.append(item)

 File ~/py313/lib/python3.13/site-
 packages/django/db/models/sql/query.py:1805, in Query.names_to_path(self,
 names, opts, allow_many, fail_on_missing)
    1797     if pos == -1 or fail_on_missing:
    1798         available = sorted(
    1799             [
    1800                 *get_field_names_from_opts(opts),
    (...)
    1803             ]
    1804         )
 -> 1805         raise FieldError(
    1806             "Cannot resolve keyword '%s' into field. "
    1807             "Choices are: %s" % (name, ", ".join(available))
    1808         )
    1809     break
    1810 # Check if we need any joins for concrete inheritance cases (the
    1811 # field lives in parent, but we are currently in one of its
    1812 # children)

 FieldError: Cannot resolve keyword 'typo' into field. Choices are: child,
 data, file, geojsongeometry, nodegroup, nodegroup_id, parenttile,
 parenttile_id, provisionaledits, resourceinstance, resourceinstance_id,
 resxres, sortorder, tileid, vwannotation
 }}}

 ----
 I'm seeing this fixed with the following, but I stopped short of
 investigating the blame to see if it was explored before. (A contributor
 might have a look into that and report back?)
 {{{#!diff
 diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
 index 20dbf7cfaa..3d9f39458b 100644
 --- a/django/db/models/sql/query.py
 +++ b/django/db/models/sql/query.py
 @@ -1820,7 +1820,7 @@ class Query(BaseExpression):
                      available = sorted(
                          [
                              *get_field_names_from_opts(opts),
 -                            *self.annotation_select,
 +                            *self.annotations,
                              *self._filtered_relations,
                          ]
                      )
 }}}

 (For anybody who followed #36380, you'll be glad to hear `.alias()` let me
 prune my hundreds of useless annotations 😅)
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36480>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/01070197a8ad5981-5d63e98f-c325-446c-9c86-c99b31668c71-000000%40eu-central-1.amazonses.com.

Reply via email to