Python 如何在 Django 中按日期范围过滤查询对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4668619/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 16:50:22  来源:igfitidea点击:

How do I filter query objects by date range in Django?

pythondjangodjango-modelsdjango-queryset

提问by user469652

I've got a field in one model like:

我在一个模型中有一个字段,例如:

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

Now, I need to filter the objects by a date range.

现在,我需要按日期范围过滤对象。

How do I filter all the objects that have a date between 1-Jan-2011and 31-Jan-2011?

如何过滤日期介于1-Jan-2011和之间的所有对象31-Jan-2011

采纳答案by crodjer

Use

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

Or if you are just trying to filter month wise:

或者,如果您只是想按月筛选:

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

Edit

编辑

As Bernhard Vallant said, if you want a queryset which excludes the specified range endsyou should consider his solution, which utilizes gt/lt (greater-than/less-than).

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

回答by Bernhard Vallant

You can use django's filterwith datetime.dateobjects:

您可以将djangofilterdatetime.date对象一起使用

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

回答by cademan

When doing django ranges with a filter make sure you know the difference between using a date object vs a datetime object. __range is inclusive on dates but if you use a datetime object for the end date it will not include the entries for that day if the time is not set.

在使用过滤器执行 Django 范围时,请确保您知道使用日期对象与日期时间对象之间的区别。__range 包含日期,但如果您使用 datetime 对象作为结束日期,则如果未设置时间,它将不包括当天的条目。

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

returns all entries from startdate to enddate including entries on those dates. Bad example since this is returning entries a week into the future, but you get the drift.

返回从 startdate 到 enddate 的所有条目,包括这些日期的条目。不好的例子,因为这是在未来一周返回条目,但你会得到漂移。

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

will be missing 24 hours worth of entries depending on what the time for the date fields is set to.

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

回答by trojjer

You can get around the "impedance mismatch" caused by the lack of precision in the DateTimeField/dateobject comparison -- that can occur if using range-- by using a datetime.timedeltato add a day to last date in the range. This works like:

您可以通过使用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])

As discussed previously, without doing something like this, records are ignored on the last day.

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

Edited to avoid the use of datetime.combine-- seems more logical to stick with date instances when comparing against a DateTimeField, instead of messing about with throwaway (and confusing) datetimeobjects. See further explanation in comments below.

编辑以避免使用datetime.combine-- 在与 a 进行比较时坚持使用日期实例似乎更合乎逻辑DateTimeField,而不是与一次性(和混淆)datetime对象混淆。请参阅下面的评论中的进一步解释。

回答by Jonhatan Fajardo

Is simple,

很简单,

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

Works for me

为我工作

回答by Bhavik Shah

Still relevant today. You can also do:

今天仍然有意义。你也可以这样做:

import dateutil
import pytz

date = dateutil.parser.parse('02/11/2019').replace(tzinfo=pytz.UTC)

回答by saran3h

To make it more flexible, you can design a FilterBackend as below:

为了让它更灵活,你可以设计一个 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