问题:如何在Django中过滤DateTimeField的日期?
我试图过滤DateTimeField
与日期比较。我的意思是:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
我得到一个空的查询集列表作为答案,因为(我认为)我不在考虑时间,但我希望“任何时间”。
Django中有一种简单的方法吗?
我在datetime中设置了时间,但不是00:00
。
I am trying to filter a DateTimeField
comparing with a date. I mean:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
I get an empty queryset list as an answer because (I think) I am not considering time, but I want “any time”.
Is there an easy way in Django for doing this?
I have the time in the datetime setted, it is not 00:00
.
回答 0
此类查询的实现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与日期比较太难 ”。
Such lookups are implemented in django.views.generic.date_based
as follows:
{'date_time_field__range': (datetime.datetime.combine(date, datetime.time.min),
datetime.datetime.combine(date, datetime.time.max))}
Because it is quite verbose there are plans to improve the syntax using __date
operator. Check “#9596 Comparing a DateTimeField to a date is too hard” for more details.
回答 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对象,因此数据库中的时间不匹配。
YourModel.objects.filter(datetime_published__year='2008',
datetime_published__month='03',
datetime_published__day='27')
// edit after comments
YourModel.objects.filter(datetime_published=datetime(2008, 03, 27))
doest not work because it creates a datetime object with time values set to 0, so the time in database doesn’t match.
回答 2
这是我使用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
包含似乎更快。
Here are the results I got with ipython’s timeit function:
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 seems to be faster.
回答 3
现在,Django具有__date queryset过滤器,可以针对开发版本中的日期查询datetime对象。因此,它将很快在1.9中可用。
Now Django has __date queryset filter to query datetime objects against dates in development version. Thus, it will be available in 1.9 soon.
回答 4
Mymodel.objects.filter(date_time_field__contains=datetime.date(1986, 7, 28))
以上是我用过的。它不仅有效,而且还具有一些固有的逻辑支持。
Mymodel.objects.filter(date_time_field__contains=datetime.date(1986, 7, 28))
the above is what I’ve used. Not only does it work, it also has some inherent logical backing.
回答 5
从Django 1.9开始,执行此操作的方法是__date
在datetime对象上使用。
例如:
MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))
As of Django 1.9, the way to do this is by using __date
on a datetime object.
For example:
MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))
回答 6
这产生与使用__year,__ month和__day相同的结果,并且似乎对我有用:
YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))
This produces the same results as using __year, __month, and __day and seems to work for me:
YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))
回答 7
假设active_on是一个日期对象,将其增加1天,然后进行范围调整
next_day = active_on + datetime.timedelta(1)
queryset = queryset.filter(date_created__range=(active_on, next_day) )
assuming active_on is a date object, increment it by 1 day then do range
next_day = active_on + datetime.timedelta(1)
queryset = queryset.filter(date_created__range=(active_on, next_day) )
回答 8
这是一种有趣的技术-我利用在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提出解决方案为止!
Here is an interesting technique– I leveraged the startswith procedure as implemented with Django on MySQL to achieve the result of only looking up a datetime through only the date. Basically, when Django does the lookup in the database it has to do a string conversion for the DATETIME MySQL storage object, so you can filter on that, leaving out the timestamp portion of the date– that way %LIKE% matches only the date object and you’ll get every timestamp for the given date.
datetime_filter = datetime(2009, 8, 22)
MyObject.objects.filter(datetime_attr__startswith=datetime_filter.date())
This will perform the following query:
SELECT (values) FROM myapp_my_object \
WHERE myapp_my_object.datetime_attr LIKE BINARY 2009-08-22%
The LIKE BINARY in this case will match everything for the date, no matter the timestamp. Including values like:
+---------------------+
| datetime_attr |
+---------------------+
| 2009-08-22 11:05:08 |
+---------------------+
Hopefully this helps everyone until Django comes out with a solution!
回答 9
这里有一篇很棒的博客文章:在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()函数。因此,这种简单的实现似乎必然与后端有关。
There’s a fantastic blogpost that covers this here: Comparing Dates and Datetimes in the Django ORM
The best solution posted for Django>1.7,<1.9 is to register a transform:
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()
Then you can use it in your filters like this:
Foo.objects.filter(created_on__date=date)
EDIT
This solution is definitely back end dependent. From the article:
Of course, this implementation relies on your particular flavor of SQL having a DATE() function. MySQL does. So does SQLite. On the other hand, I haven’t worked with PostgreSQL personally, but some googling leads me to believe that it does not have a DATE() function. So an implementation this simple seems like it will necessarily be somewhat backend-dependent.
回答 10
嗯..我的解决方案正在工作:
Mymodel.objects.filter(date_time_field__startswith=datetime.datetime(1986, 7, 28))
Hm.. My solution is working:
Mymodel.objects.filter(date_time_field__startswith=datetime.datetime(1986, 7, 28))
回答 11
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)
回答 12
在Django 1.7.6中工作:
MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
In Django 1.7.6 works:
MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
回答 13
请参阅文章Django文档
ur_data_model.objects.filter(ur_date_field__gte=datetime(2009, 8, 22), ur_date_field__lt=datetime(2009, 8, 23))
See the article Django Documentation
ur_data_model.objects.filter(ur_date_field__gte=datetime(2009, 8, 22), ur_date_field__lt=datetime(2009, 8, 23))