我如何过滤查询对象的日期范围在Django?

我在一个模型中有一个字段:

class Sample(models.Model):
date = fields.DateField(auto_now=False)

现在,我需要按日期范围筛选对象。

如何过滤日期在1-Jan-201131-Jan-2011之间的所有对象?

441949 次浏览

你可以使用django的filterdatetime.date对象:

import datetime
samples = Sample.objects.filter(sampledate__gte=datetime.date(2011, 1, 1),
sampledate__lte=datetime.date(2011, 1, 31))

使用

Sample.objects.filter(date__range=["2011-01-01", "2011-01-31"])

或者如果你只是想按月份过滤:

Sample.objects.filter(date__year='2011',
date__month='01')

编辑

正如Bernhard Vallant所说,如果你想要一个不包含specified range ends的查询集,你应该考虑他的解决方案,它使用了gt/lt(大于/小于)。

当使用django范围过滤器时,确保你知道date对象和datetime对象的区别。__range包含日期,但如果你使用一个datetime对象作为结束日期,如果没有设置时间,它将不包括当天的条目。

from datetime import date, timedelta


startdate = date.today()
enddate = startdate + timedelta(days=6)
Sample.objects.filter(date__range=[startdate, enddate])

返回从开始日期到结束日期的所有条目,包括这些日期的条目。这是一个糟糕的例子,因为这是在未来一周返回条目,但您可以得到漂移。

from datetime import datetime, timedelta


startdate = datetime.today()
enddate = startdate + timedelta(days=6)
Sample.objects.filter(date__range=[startdate, enddate])

将丢失24小时的条目,这取决于日期字段的时间设置。

你可以通过使用datetime.timedelta在范围内的最后日期后添加一天来避免由于DateTimeField/date对象比较中缺乏精度而导致的“阻抗不匹配”——如果使用范围就会发生这种情况。这是这样的:

start = date(2012, 12, 11)
end = date(2012, 12, 18)
new_end = end + datetime.timedelta(days=1)


ExampleModel.objects.filter(some_datetime_field__range=[start, new_end])

如前所述,如果不这样做,最后一天的记录将被忽略。

编辑以避免使用datetime.combine——在与DateTimeField比较时,坚持使用date实例似乎更合乎逻辑,而不是使用丢弃(并令人困惑)的datetime对象。详见下面的评论。

很简单,

YourModel.objects.filter(YOUR_DATE_FIELD__date=timezone.now())

对我有用

为了使它更灵活,你可以这样设计一个FilterBackend:

class AnalyticsFilterBackend(generic_filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
predicate = request.query_params # or request.data for POST


if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is not None:
queryset = queryset.filter(your_date__range=(predicate['from_date'], predicate['to_date']))


if predicate.get('from_date', None) is not None and predicate.get('to_date', None) is None:
queryset = queryset.filter(your_date__gte=predicate['from_date'])


if predicate.get('to_date', None) is not None and predicate.get('from_date', None) is None:
queryset = queryset.filter(your_date__lte=predicate['to_date'])
return queryset

可以使用"__range" 例如:

from datetime import datetime
start_date=datetime(2009, 12, 30)
end_date=datetime(2020,12,30)
Sample.objects.filter(date__range=[start_date,end_date])

模型

date = models.DateField()

视图

def get_queryset(self):


fromDate = self.request.query_params.get('fromDate',None)
toDate = self.request.query_params.get('toDate',None)
response  = yourModel.objects.filter(date__gte=fromDate,date__lte=toDate)
return response