我如何在Django中过滤一个DateTimeField的日期?

我试图过滤一个DateTimeField比较日期。我的意思是:

MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))

我得到一个空的查询集列表作为答案,因为(我认为)我没有考虑时间,但我想要“任何时间”。

Django中有简单的方法来做这个吗?

我在datetime中设置了时间,它不是00:00

260784 次浏览
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对象,因此数据库中的时间不匹配。

参见文章Django的文档

ur_data_model.objects.filter(ur_date_field__gte=datetime(2009, 8, 22), ur_date_field__lt=datetime(2009, 8, 23))
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)

这样的查找在django.views.generic.date_based中实现,如下所示:

{'date_time_field__range': (datetime.datetime.combine(date, datetime.time.min),
datetime.datetime.combine(date, datetime.time.max))}

因为它相当冗长,所以计划使用__date操作符改进语法。查看“比较DateTimeField和日期太难了”以获得更多详细信息。

这产生了与使用__year, __month,和__day相同的结果,并且似乎对我有用:

YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))

嗯. .我的解决方案是有效的:

Mymodel.objects.filter(date_time_field__startswith=datetime.datetime(1986, 7, 28))
Mymodel.objects.filter(date_time_field__contains=datetime.date(1986, 7, 28))

以上就是我所使用的。它不仅有效,而且有一些内在的逻辑支持。

下面是我使用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

包含似乎更快。

这里有一个有趣的技术——我利用Django在MySQL上实现的startswith过程来实现仅通过日期查找datetime的结果。基本上,当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拿出解决方案!

假设active_on是一个日期对象,将其增加1天,然后执行range

next_day = active_on + datetime.timedelta(1)
queryset = queryset.filter(date_created__range=(active_on, next_day) )

现在Django在开发版本中有__date queryset过滤器来根据日期查询datetime对象。因此,它将很快在1.9中可用。

这里有一篇很棒的博客文章介绍了这个:比较Django ORM中的日期和日期时间

Django>1.7的最佳解决方案是注册一个转换:

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()函数。因此,如此简单的实现似乎必然是后端依赖的。

从Django 1.9开始,这样做的方法是在datetime对象上使用__date

例如< p >: MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22)) < / p >

在Django 1.7.6中工作:

MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
person = Profile.objects.get(id=1)


tasks = Task.objects.filter(assigned_to=person, time_stamp__year=person.time_stamp.utcnow().year)

我所有的模型都有time_stamp,所以我使用person对象来获取当前年份

你可以这样做

MyObject.objects.filter(datetime_field__date=datetime.date(2009,8,22))

或者如果你想在两个日期之间过滤

MyObject.objects.filter(
datetime_field__date__range=(datetime.date(2009,8,22), datetime.date(2009,9,22))
)

您可以在某些日期范围之间进行筛选

2016-01-01 00:00:00 <--> 2016-04-01 23:59:59.99999

User.objects.filter(date_joined__gte=datetime.combine(datetime.strptime('2016-
01-01', '%Y-%d-%m'), datetime.min.time()),
date_joined__lte=datetime.combine(datetime.strptime('2016-04-01', '%Y-%d-%m'),
datetime.max.time())).count()

2016-01-01 00:00:00 <--> 2016-01-14 00:00:00

User.objects.filter(date_joined__gte='2016-01-01', date_joined__lte='2016-1-14').count()

很简单,如果你有一个datetimefield你可以使用datetime。date。today()

context['now'] = Mymodel.objects.filter(date_time_field=datetime.date.today())

你可以根据日期进行过滤,因为日期格式与django的日期格式相同。默认格式为“ISO YYYY-MM-DD”

target_date = "2009-08-22"
qs = MyObject.objects.filter(datetime_attr__date=target_date)
MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))