Python 如何在django中包含条件order_by?
我需要根据布尔字段对查询集的两个部分进行不同的排序。 -bool_val==True的行应排在第一位,并按日期a升序排序。 -bool_val==False的行应排在第二位,并按日期b降序排序 我得到的最接近的是Python 如何在django中包含条件order_by?,python,django,sorting,django-1.10,Python,Django,Sorting,Django 1.10,我需要根据布尔字段对查询集的两个部分进行不同的排序。 -bool_val==True的行应排在第一位,并按日期a升序排序。 -bool_val==False的行应排在第二位,并按日期b降序排序 我得到的最接近的是 MyModel.objects.all().annotate( sort_order=Case( When(bool_val=True, then=('date_a')), default='date_b') ).order_by('-
MyModel.objects.all().annotate(
sort_order=Case(
When(bool_val=True, then=('date_a')),
default='date_b')
).order_by('-bool_val', 'sort_order')
但这是按相同的顺序排列的。如果我需要排序的值是数值,那么我会在注释中将一个集合乘以-1,但它们是日期值,所以这不起作用
我还研究了创建两个单独的查询集并将它们组合起来,但是union()直到1.11才可用,我必须支持1.10,我发现的其他组合查询集的方法要么不保持顺序,要么不会生成查询集(或者两者都有)。(我不清楚union()是否保留顺序,但这是没有意义的,所以我也没有深入研究。)最后必须是django QuerySet对象。您应该能够使用表达式将日期时间转换为时间戳,这样您就可以对它们进行否定 对于MySQL,这是
UNIX\u TIMESTAMP
函数
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')
对于PostgreSQL,这是EXTRACT(从带有时区“”的时间戳中提取历元)
有点麻烦。。。而且可能很慢。我没有测试过这个这就是最终起作用的原因:
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',
)
您可以在日期上使用负号:
.order\u by('bool\u val','-sort\u order')
是的,但您不能有条件地这样做。这是一个好主意,但django试图将“带时区的时间戳的历元”
解释为字段名时遇到了麻烦。我尝试了几个变体,但最终找到了一个更优雅的解决方案;请参阅我发布的答案。感谢您提出此解决方案。我遇到了与@CharlotteMays相同的问题,最后我使用了这个:Extract('date\u a','epoch')
代替了Func(F('date\u a'),function='UNIX\u TIMESTAMP')
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',
)