2016-05-23 79 views
1

在Django中,是否可以通過字段是否爲None來進行排序,而不是字段本身的值?Django:通過評估日期是否爲空來排序

我知道我可以發送QuerySet到python sorted()但我想保留它作爲後續過濾的QuerySet。所以,我寧願在QuerySet中訂購。

例如,我有一個termination_date字段,我想先排序沒有terminate_date的字段,然後我想按不同的字段排序,如last_name,first_name。

這是可能的還是我堅持使用sorted(),然後必須使用包含的ID做一個完整的新查詢並在新的QuerySet上運行sorted()?我可以做到這一點,但寧願不浪費開銷,並使用QuerySets的美麗,他們不運行,直到評估。我的模型是Employee,它有三個字段'first_name(varchar)','last_name(varchar)'和'termination_date(date)',我怎麼從Django獲得這個SQL呢? :

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" 

回答

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之後那些有some_field。並且每組行應按some_other_field排序。

當然,CASE/WHEN會讓你的問題變得更加麻煩,但我不知道如何讓Django ORM輸出它。也許別人會有更好的答案。

+0

令人驚訝的是,我一直與Django合作多年,從未遇到過Case類。非常感謝,非常完美! – Furbeenator

+0

@Furbeenator>這是一個相當新的增加。我認爲Django 1.7,甚至1.8。 djangoproject團隊試圖通過使用可組合的查詢表達式使Django ORM更具表達性來殺死'.extra()'方法。更好的封裝和便攜性。 – spectras

+0

這是有道理的,我不得不承認,自從1.3版本以來,我一直在維護Django,並沒有看過所有已更新的最新的兩個發行說明。對我感到遺憾...... -/ – Furbeenator

1

Spectras的回答正常,但它只是通過'null或不是'來命令你的記錄。還有,讓你把空的日期,無論你想他們在你的日期排序較短的方式 - 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中所述。

+0

謝謝你的回答,@schwobaseggl!我還沒有聽說過'Coalesce'。它也必須是一個相對較新的加法。你知道是否有'Coalesce'或使用@spectras提到的'Case'語句的資源優勢嗎? – Furbeenator

+0

它已被添加到1.8中。看起來,這兩者非常相似:http://stackoverflow.com/questions/15523000/coalesce-or-case-more-efficient-and-or-standard。你可以用'str(queryset.query)'檢查生成的SQL,它們差別不大。聚合基本上是一條捷徑。 – schwobaseggl