Skip to content

Instantly share code, notes, and snippets.

@jperelli
Last active January 26, 2024 11:56
Show Gist options
  • Save jperelli/9b7fa2352c9ea383ad3978bb051ff510 to your computer and use it in GitHub Desktop.
Save jperelli/9b7fa2352c9ea383ad3978bb051ff510 to your computer and use it in GitHub Desktop.
Conditional order by in django's ORM
"""
Some table has two Date fields: expiredate and SALexpiredate
Both fields can be null
when SALexpiredate is not null, overrides expiredate
when ordering:
if SALexpiredate is not null, that field needs to be used
otherwise fallback to use expiredate
"""
from django.db.models import DateField, Case, When, F
queryset.annotate(
expiredate_salexpiredate=Case(
When(salexpiredate__isnull=False, then=F('salexpiredate')),
default=F('expiredate'),
output_field=DateField(),
),
).order_by('-expiredate_salexpiredate')
"""
This is a simpler approach for the same problem I didn't know I could do.
I think that this is far better, but the previous could be useful in some use cases.
"""
from django.db.models.functions import Coalesce
queryset.order_by(
Coalesce(
F('salexpiredate'),
F('expiredate')
).desc()
)
@cb109
Copy link

cb109 commented Jun 17, 2019

Thanks for this example. It's worth noting that Coalesce is great when you want to choose the first non-null value. If any other conditions should be met (e.g. comparing datetimes), your first approach is the solution, adding queries inside the When() block as needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment