#33678: order_by crash when sorting by a foreign key referencing a Model with an
ordering that includes expressions
-------------------------------------+-------------------------------------
     Reporter:  Eduardo Rivas        |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  4.0
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Simon Charette):

 * type:  Uncategorized => Bug
 * component:  contrib.admin => Database layer (models, ORM)
 * stage:  Unreviewed => Accepted


Comment:

 Thank you for your report. I vaguely remember that this was brought up
 already previously but I can't find an existing ticket on the subject.

 The issue here is not the admin as you'll get the same crash if you try to
 do `list(QuotePartMaterial.objects.order_by('material'))`.

 What we're lacking
 
[https://github.com/django/django/blob/9d04711261156c487c6085171398070ea3df8122/django/db/models/sql/compiler.py#L909-L916
 is a bit of logic ] that translates `order_by('material')` to
 `order_by(Lower('material__code'))` instead of naively doing
 `.order_by(Lower('code'))` when we're not dealing with a field inherited
 through a parent link. This is something that was overlooked in #30557.

 I suggest we take an approach similar to `Expression.replace_references`
 in [https://github.com/django/django/pull/14625/ the ungoing work for
 database constraint validation] and introduce
 `Expression.prefix_references` that goes along these lines


 {{{#!python
 def prefix_references(self, prefix):
     clone = self.copy()
     clone.set_source_expressions(
         [
             F(f"{prefix}{expr.name}")
             if isinstance(expr, F)
             else expr.prefix_references(prefix)
             for expr in self.get_source_expressions()
         ]
     )
     return clone
 }}}

 It will then be trivial to adjust `SQLCompiler.find_ordering_name` to call
 `item.prefix_references(f"{field.name}{LOOKUP_SEP}")` when appropriate.

 Is this something you'd be interesting in fixing and writing tests for
 yourself Eduardo? This seems like a good introduction ticket to a few ORM
 components if this is something you've been curious about.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33678#comment:1>
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 on the web visit 
https://groups.google.com/d/msgid/django-updates/010701808d4066e7-ea1723bc-8b22-4df3-8e10-39825867e55e-000000%40eu-central-1.amazonses.com.

Reply via email to