How can I include a conditional order_by in django?
--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Droplet of life
--
Chapters
00:00 How Can I Include A Conditional Order_by In Django?
01:11 Answer 1 Score 1
01:49 Accepted Answer Score 10
02:04 Answer 3 Score 0
02:21 Thank you
--
Full question
https://stackoverflow.com/questions/4427...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #django #sorting #django110
#avk47
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Droplet of life
--
Chapters
00:00 How Can I Include A Conditional Order_by In Django?
01:11 Answer 1 Score 1
01:49 Accepted Answer Score 10
02:04 Answer 3 Score 0
02:21 Thank you
--
Full question
https://stackoverflow.com/questions/4427...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #django #sorting #django110
#avk47
ACCEPTED ANSWER
Score 10
This is what ended up working:
MyModel.objects.annotate(
sort_order_true=Case(
When(bool_val=True, then=('date_a')),
default=None
),
sort_order_false=Case(
When(bool_val=False, then=('date_b')),
default=None
)
).order_by(
'sort_order_true',
'-sort_order_false',
)
ANSWER 2
Score 1
You should be able to use a Func expression to convert your datetimes into timestamps so that you can negate them.
For MySQL this is the UNIX_TIMESTAMP function
MyModel.objects.annotate(
sort_order=Case(
When(bool_val=True, then=Func(F('date_a'), function='UNIX_TIMESTAMP')),
When(bool_val=False, then=Value(0) - Func(F('date_b'), function='UNIX_TIMESTAMP')),
)
).order_by('-bool_val', 'sort_order')
For PostgreSQL this is EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '<datetime>')
MyModel.objects.annotate(
sort_order=Case(
When(bool_val=True, then=Func(F('date_a'), function='UNIX_TIMESTAMP')),
When(bool_val=False, then=Value(0) - Func('EPOCH FROM TIMESTAMP WITH TIME ZONE', F('date_b'), function='EXTRACT', arg_joiner=' ')),
)
).order_by('-bool_val', 'sort_order')
A little cumbersome... and potentially slow. I have not tested this
ANSWER 3
Score 0
This is an another approach for the same problem. I think that this is would work better in null cases(if true or false is not available), but the previous could be helpful in some use cases.
from django.db.models import F
from django.db.models.functions import Coalesce
MyModel.objects.order_by(
Coalesce(F('date_a'), F('date_b')).desc()
)