2016-08-22 192 views
1

我有一個包含日期時間字段的模型(代表'作業'),名爲date_created。我有另一個叫date_modifiedDjango - 按日期而不是日期時間對Queryset進行排序

我想按-date_modified排序,以便最近修改的'jobs'位於我的列表頂部。問題在於,每次更新時間戳時,多個正在運行的作業都會繼續重新排序。如果date_modified字段按照如果它是DateField排序,那麼我可以先排序所有'今天'已修改的'作業',然後從第二個值(如date_created)中排序,以便它們會隨着時間戳被修改,不會更改列表中的位置。

這是我現在有:

queryset = DataCollection.objects.all().order_by('-date_modified','-date_created') 

我發現了一篇相關的文章,但似乎與1.9版本過時: Django sorting by date(day)

UPDATE

目前的修復,我看着是這樣的:

queryset = DataCollection.objects.all().extra(select = 
{'custom_dt': 'date(date_modified)'}).order_by('-custom_dt','-date_created') 

這與@lampslave建議的內容最爲相似,但它使用了extra方法,這種方法將來會被棄用......我認爲我不會很快升級到Django的更高版本,但是這個使我的胃有點不安。

+0

如果您使用的時區,那就要小心日期時間的日期取決於您的日期時間所在的時區。 –

+0

好點。爲什麼DateTimeField的包含時區信息? – Dan

+0

如果您在工作時區感知日期時間,則時區通常被視爲屬於表示層。日期時間應在UTC內部並儘可能晚地進行轉換。請參閱https://docs.djangoproject.com/en/1.10/topics/i18n/timezones/ –

回答

2

我會得到查詢集,然後在這種情況下在視圖中進行排序。

sorted(DataCollection.objects.all(), key = lambda x: x.date_modified.date(), reverse = True) 

要按兩個鍵就可以使用attrgetter,在方法文檔描述/排序文檔進行排序。

+0

這看起來像是一個非常好的方法,但我在使用Django DRF路由時出現「no base_name」錯誤,所以現在,我試圖在查詢本身做這一切,因爲我不能返回一個列表出於某種原因。 – Dan

+1

如果你在1.10,你可以用Cast來做一些事情(https://docs.djangoproject.com/en/1。10/ref/models/database-functions /#cast)或者使用新的日期函數之一(https://docs.djangoproject.com/en/1.10/ref/models/database-functions/#module-django.db .models.functions.datetime)。然而,我大部分在1.9.x,所以我沒有任何實際的經驗。 – souldeux

+0

我使用1.8所以演員陣容和其他一些選項出門。我認爲將來的正確答案是每當可用時都使用__date。 – Dan

0

如果你的數據庫支持datetime_to_date轉換,你可以嘗試這樣的事:

DataCollection.objects.all().annotate(date_created__date=RawSQL('DATE(date_created)',())).order_by('-date_created__date') 
+0

這看起來幾乎是正確的,但我覺得有一個純粹的「Django」方式來做到這一點,所以我沒有使用原始SQL查詢。不是所有的數據庫都有datetimefield - > datefield轉換嗎? Django不應該在暴露API的情況下采取一些方法來做到這一點嗎? – Dan

+0

查看對souldeux的回答。嘗試使用新的表達式或函數來代替RawSQL。 – lampslave

+0

你是什麼意思由「新表達」 – Dan

0

我覺得souldeux答案很可能是比這更整潔了很多,但另一種解決方案可能是單獨查詢,則它們連接在一起。我想沿着這些線路的東西

from itertools import chain 
import datetime 

# get just todays data ordered by date modified 
today_min = datetime.datetime.combine(datetime.date.today(), datetime.time.min) 
today_max = datetime.datetime.combine(datetime.date.today(), datetime.time.max) 
data_set1 = DataCollection.objects.filter(date_modified__range=(today_min, today_max)).order_by('-date_modified') 

# get the rest of the data 
data_set2 = DataCollection.objects.all().exclude(date_modified__range=(today_min, today_max)).order_by('-date_created') 

# join it all together 
all_list = list(chain(data_set1, data_set2)) 

我認爲Django的曾計劃推出一款__date查詢選擇我不知道這是否是尚未提供但也可能有助於

相關問題