在Django中,是否可以通过字段是否为None来排序,而不是字段本身的值?
我知道我可以将QuerySet发送到python sorted()
,但是我想将它保存为QuerySet以便后续过滤。所以,我更喜欢在QuerySet中订购。
例如,我有一个termination_date字段,我想首先排序没有termination_date的字段,然后我想按不同的字段排序,比如last_name,first_name。
这是可能的还是我使用sorted()
而不得不使用包含的ID执行一个全新的查询并在新的QuerySet上运行sorted()
?我可以做到这一点,但我不想浪费开销,并使用QuerySet的优点,直到评估它们才会运行。
翻译,我怎么能从Django获取这个SQL,假设我的应用是employee
,我的模型是Employee
,它有三个字段'first_name(varchar)','last_name(varchar)',和'termination_date(date)':
SELECT
"employee_employee"."last_name",
"employee_employee"."first_name",
"employee_employee"."termination_date"
FROM "employee_employee"
ORDER BY
"employee_employee"."termination_date" IS NOT NULL,
"employee_employee"."last_name",
"employee_employee"."first_name"
答案 0 :(得分:1)
您应该可以按query expressions订购,如下所示:
from django.db.models import IntegerField, Case, Value, When
MyModel.objects.all().order_by(
Case(
When(some_field=None, then=Value(1)),
default=Value(0),
output_field=IntegerField(),
).asc(),
'some_other_field'
)
我无法在这里进行测试,因此可能需要稍微调整一下,但是这应该在具有some_field
的行之后放置具有NULL some_field
的行。每组行应按some_other_field
排序。
当然,CASE / WHEN比您提出的问题更麻烦,但我不知道如何让Django ORM输出。也许其他人会有更好的答案。
答案 1 :(得分:1)
Spectras的回答很好,但它只按'null或not'命令你的记录。有一种较短的方式可让您在日期排序中的任何位置放置空日期 - Coalesce
:
from django.db.models import Value
from django.db.models.functions import Coalesce
wayback = datetime(year=1, month=1, day=1) # or whatever date you want
MyModel.objects
.annotate(null_date=Coalesce('date_field', Value(wayback)))
.order_by('null_date')
这实际上将按字段'date_field'
排序,所有包含date_field == None
的记录将按顺序排列,就好像它们的日期为wayback
一样。这与PostgreSQL完美配合,但可能需要在MySQL中进行一些原始的sql转换,如documentation中所述。