Django - 按日期而不是日期时间对Queryset进行排序

问题描述:

我有一个包含日期时间字段的模型(代表'作业'),名为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/ –

我会得到查询集,然后在这种情况下在视图中进行排序。

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

如果你的数据库支持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

我觉得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查询选择我不知道这是否是尚未提供但也可能有助于