Django queryset order_by绝对值

Bil*_*ong 4 python django python-3.x

我有一个具有description属性和balance属性的查询集.目前,当我生成查询集时,它从最小到最大排序 - -

Model.objects.order_by('balance')

#output

Thing1          -120000
Thing2             -300
Thing3             7000
Thing4           100000
Run Code Online (Sandbox Code Playgroud)

我想订购的是降低绝对值,结果如下:

#Desired Output

Thing1          -120000
Thing4           100000
Thing3             7000
Thing2             -300
Run Code Online (Sandbox Code Playgroud)

我试过在里面传递各种方法,order_by()但我认为它需要是一个SQL类型的参数 - 我无法弄清楚.我发现这个使用了func expression注释时.我无法使用它order_by并且文档没有多大帮助.

有没有办法以这种方式订购查询集?

nev*_*ner 7

您可以通过注释值注释绝对值和顺序.您可以使用-sign来指示降序:

from django.db.models import Func, F

Model.objects.annotate(abs_balance=Func(F('balance'), function='ABS')).order_by('-abs_balance')
Run Code Online (Sandbox Code Playgroud)


Vid*_*dak 7

@neverwalkaloner 的回答非常好,但在处理datetime对象时不起作用,例如,如果您想按到某个特定时间戳的距离对对象进行排序。

例如:

queryset.annotate(
    distance=Func(F('datetime') - datetime_goal, function='ABS')
).order_by('distance')
Run Code Online (Sandbox Code Playgroud)

失败ProgrammingError: function abs(interval) does not exist,在这个问题中有解释。

在这种情况下,您可以使用Case表达式来模拟绝对值,如下所示:

from django.db.models import Case, When
queryset.annotate(
    distance=Case(
        When(datetime__gte=datetime_goal, then=F('datetime')-datetime_goal),
        When(datetime__lt=datetime_goal, then=datetime_goal-F('datetime')),
    )
).order_by('distance')
Run Code Online (Sandbox Code Playgroud)