我试图过滤DateTimeField
与日期比较。我的意思是:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
我得到一个空的查询集列表作为答案,因为(我认为)我不在考虑时间,但我希望“任何时间”。
Django中有一种简单的方法吗?
我在datetime中设置了时间,但不是00:00
。
我试图过滤DateTimeField
与日期比较。我的意思是:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
我得到一个空的查询集列表作为答案,因为(我认为)我不在考虑时间,但我希望“任何时间”。
Django中有一种简单的方法吗?
我在datetime中设置了时间,但不是00:00
。
Answers:
此类查询的实现django.views.generic.date_based
方式如下:
{'date_time_field__range': (datetime.datetime.combine(date, datetime.time.min),
datetime.datetime.combine(date, datetime.time.max))}
因为它很冗长,所以有计划使用__date
运算符来改进语法。有关更多详细信息,请检查“ #9596将DateTimeField与日期比较太难 ”。
Q(created__gte=datetime.combine(created_value, time.min))
Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
YourModel.objects.filter(datetime_published__year='2008',
datetime_published__month='03',
datetime_published__day='27')
//在评论后编辑
YourModel.objects.filter(datetime_published=datetime(2008, 03, 27))
不起作用,因为它创建了一个时间值设置为0的datetime对象,因此数据库中的时间不匹配。
这是我使用ipython的timeit函数得到的结果:
from datetime import date
today = date.today()
timeit[Model.objects.filter(date_created__year=today.year, date_created__month=today.month, date_created__day=today.day)]
1000 loops, best of 3: 652 us per loop
timeit[Model.objects.filter(date_created__gte=today)]
1000 loops, best of 3: 631 us per loop
timeit[Model.objects.filter(date_created__startswith=today)]
1000 loops, best of 3: 541 us per loop
timeit[Model.objects.filter(date_created__contains=today)]
1000 loops, best of 3: 536 us per loop
包含似乎更快。
contains
解决方案时,我收到了错误消息:Unable to get repr for <class 'django.db.models.query.QuerySet'>
startswith
解决方案
现在,Django具有__date queryset过滤器,可以针对开发版本中的日期查询datetime对象。因此,它将很快在1.9中可用。
这产生与使用__year,__ month和__day相同的结果,并且似乎对我有用:
YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))
这是一种有趣的技术-我利用在Django上在MySQL上实现的startswith过程来实现只在日期中查找日期时间的结果。基本上,当Django在数据库中进行查找时,它必须对DATETIME MySQL存储对象进行字符串转换,因此您可以对此进行过滤,而忽略日期的时间戳部分-这样%LIKE%仅与日期匹配对象,您将获得给定日期的每个时间戳。
datetime_filter = datetime(2009, 8, 22)
MyObject.objects.filter(datetime_attr__startswith=datetime_filter.date())
这将执行以下查询:
SELECT (values) FROM myapp_my_object \
WHERE myapp_my_object.datetime_attr LIKE BINARY 2009-08-22%
在这种情况下,无论时间戳如何,LIKE BINARY都将匹配日期中的所有内容。包括以下值:
+---------------------+
| datetime_attr |
+---------------------+
| 2009-08-22 11:05:08 |
+---------------------+
希望这对所有人都有帮助,直到Django提出解决方案为止!
这里有一篇很棒的博客文章:在Django ORM中比较日期和日期时间
为Django> 1.7,<1.9发布的最佳解决方案是注册一个转换:
from django.db import models
class MySQLDatetimeDate(models.Transform):
"""
This implements a custom SQL lookup when using `__date` with datetimes.
To enable filtering on datetimes that fall on a given date, import
this transform and register it with the DateTimeField.
"""
lookup_name = 'date'
def as_sql(self, compiler, connection):
lhs, params = compiler.compile(self.lhs)
return 'DATE({})'.format(lhs), params
@property
def output_field(self):
return models.DateField()
然后可以在过滤器中使用它,如下所示:
Foo.objects.filter(created_on__date=date)
编辑
此解决方案绝对取决于后端。从文章:
当然,此实现依赖于具有DATE()函数的SQL的特定风格。MySQL确实如此。SQLite也是如此。另一方面,我还没有亲自使用PostgreSQL,但是通过谷歌搜索使我相信它没有DATE()函数。因此,这种简单的实现似乎必然与后端有关。
return '{}::date'.format(lhs), params
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)