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.