Django:通过评估日期是否为空来排序

时间:2016-05-23 19:02:06

标签: python django

在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"

2 个答案:

答案 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中所述。