FieldError when `ordering` uses functions and `order_by` includes the related model.

When using functions in ordering and then using an order_by("related") on a related model, Django might fail to find the field:

Models:

from django.db import models


class ModelA(models.Model):
    name = models.CharField(max_length=1024)

    class Meta:
        ordering = (models.functions.Lower('name'), )


class ModelB(models.Model):
    ref = models.ForeignKey(ModelA, on_delete=models.CASCADE)

causes the following query to fail:

ModelB.objects.order_by("ref")

Error:

Traceback (most recent call last):
  File "dj4bug/dj4bug/buggy/tests.py", line 7, in test_query_order_by_ref
    list(ModelB.objects.order_by('ref'))
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 320, in __iter__
    self._fetch_all()
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 1507, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 57, in __iter__
    results = compiler.execute_sql(
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1348, in execute_sql
    sql, params = self.as_sql()
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 573, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup()
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 65, in pre_sql_setup
    order_by = self.get_order_by()
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 416, in get_order_by
    resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None)
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/expressions.py", line 260, in resolve_expression
    [
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/expressions.py", line 261, in <listcomp>
    expr.resolve_expression(query, allow_joins, reuse, summarize)
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/expressions.py", line 762, in resolve_expression
    c.source_expressions[pos] = arg.resolve_expression(
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/expressions.py", line 655, in resolve_expression
    return query.resolve_ref(self.name, allow_joins, reuse, summarize)
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1922, in resolve_ref
    join_info = self.setup_joins(
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1773, in setup_joins
    path, final_field, targets, rest = self.names_to_path(
  File "dj4bug/.venv/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1677, in names_to_path
    raise FieldError(
django.core.exceptions.FieldError: Cannot resolve keyword 'name' into field. Choices are: id, ref, ref_id

If your ModelB has a name then the error gets masked. Django issues the wrong query with ORDER BY LOWER("modelb"."name") instead of the related ref’s name.

I’ve created a repo with a demo: GitHub - mvaled/django4-bug-ordering-with-functions: Showcases a bug when ordering uses functions.

I’ve just found this is reported here: #33678 (order_by crash when sorting by a foreign key referencing a Model with an ordering that includes expressions) – Django