Last active
January 26, 2024 11:56
-
-
Save jperelli/9b7fa2352c9ea383ad3978bb051ff510 to your computer and use it in GitHub Desktop.
Conditional order by in django's ORM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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() | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 theWhen()
block as needed.