Djangoでクエリオブジェクトを日付範囲でフィルタリングするにはどうすればよいですか?


248

次のような1つのモデルにフィールドがあります。

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

次に、日付範囲でオブジェクトをフィルタリングする必要があります。

1-Jan-2011との間の日付を持つすべてのオブジェクトをフィルタリングするにはどうすればよい31-Jan-2011ですか?

回答:


409

使用する

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(より大/小)を使用する彼のソリューションを検討する必要があります。


date1のデータ型は何ですか?日付時刻オブジェクトを取得しました。
user469652 2011年

8
@dcordjer:__range境界線(sqlのようなBETWEEN)が含まれていると言う必要があります。境界線を含めたくない場合は、私のgt / ltソリューションを使用する必要があります...
Bernhard Vallant

これは本質的に任意の順序で並べ替えられますか?ある場合、どの順序ですか?ありがとう。
Richard Dunn、

1
@RichardDunn順序は、モデルのデフォルトの順序、または上記でorder_by生成さQuerySetれたを使用する場合に基づきますfilter。私は何年もDjangoを使っていません。
crodjer 2016年

date__rangeの場合、翌月の01を指定する必要があります。これは、日付の00:00:00.0000に変換されるexmaplinsのドキュメントへのリンクです。したがって、範囲の最終日は含まれません。docs.djangoproject.com/en/1.10/ref/models/querysets/#range この場合、私は次を使用します:date__range = ["%s-%s-1"%(year、month)、 "%s-%s- 1 "%(year、int(month)+1)]
SpiRail

195

あなたは使用することができますDjangoのfilter持つdatetime.dateオブジェクトを

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

1日目と31日目を含むすべてを取得するには、gteを使用する必要がありますか?
Sam Stoelinga、2011年

1
このメソッドをcrodjerよりも使用する利点は、文字列ではなくdatetimeオブジェクトを渡すことができることです。
Brian Kung

79

フィルターを使用してdjangoの範囲を実行するときは、日付オブジェクトと日付時刻オブジェクトの違いを理解してください。__rangeは日付に含まれますが、終了日にdatetimeオブジェクトを使用する場合、時刻が設定されていなければ、その日のエントリは含まれません。

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

startdateからenddateまでのすべてのエントリを、それらの日付のエントリを含めて返します。これは1週間後のエントリを返すため、悪い例ですが、ドリフトが発生します。

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

日付フィールドの時刻の設定に応じて、24時間分のエントリが欠落します。


5
私はそれをインポートする方法を注意することが重要だと思いdateオブジェクトを: >>> from datetime import date >>> startdate = date.today()
アレックス・スペンサー

19

範囲DateTimeField/dateを使用している場合に発生する可能性がある、オブジェクト比較の精度の欠如が原因で発生する「インピーダンスの不一致」を回避するには、datetime.timedeltaを使用して範囲の最後の日付に日を追加します。これは次のように機能します:

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使い捨ての(そして混乱を招く)datetimeオブジェクトをいじるのではなく、と比較するときに日付インスタンスに固執する方が論理的です。以下のコメントで詳細な説明を参照してください。


1
切り捨てメソッドでこれを簡略化する素晴らしいDeloreanライブラリがあります。delorean.readthedocs.org
en

@tojjer:有望に見えますが、ここでは切り捨てメソッドをどのように使用しますか?
ユージーン2014年

@eugene:これらすべての月の後に、私はこれを今すぐもう一度探りました、そしてあなたはそれが結局この状況で本当に役に立たないということで正しいです。私が考えることができる唯一の方法は、元の応答で提案されているとおりです。これは、日付インスタンスに対してフィルタリングするときに、日時モデルフィールドと比較するための追加の「パディング」を提供することです。これは上記のようにdatetime.combineメソッドを介して行うことができますが、範囲内の開始日/終了日にtimedelta(days = 1)を追加するだけで不一致に対応する方が少し簡単であることがわかりました- -問題によって異なります。
trojjer 2014年

だから、Example.objects.filter(created__range=[date(2014, 1, 1), date(2014, 2, 1)])上で作成されたオブジェクトが含まれていないでしょうdate(2014, 2, 1)@cademanが親切に説明したように、。しかし、1日を追加して終了日を増やした場合、欠落しているオブジェクトをカバーするクエリセットが得られます(date(2014, 2, 2)同じ癖のために作成されたオブジェクトは省略されます)。ここでの厄介なことは、で指定された「手動」範囲created__gte ... created__lte=date(2014, 2, 1)も機能しないことです。これは、明らかに直観に反するIMHOです。
trojjer 2014年

1
@tojjer:datetime_field__range = [delorean.parse( '2014-01-01')。date、delorean.parse( '2014-02-01')。date]は私にとって
有効

1

シンプルです

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

私のために働く


3
これは私にも、わかりやすいように初心者にも機能しました:(date__date = ...)は({whateverColumnTheDateIsCalled} __ date)を意味します
Ryan Dines

2
OPは範囲を求めた
aliasav

1

より柔軟にするために、以下のように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

-2

今日もまだ関連があります。あなたも行うことができます:

import dateutil
import pytz

date = dateutil.parser.parse('02/11/2019').replace(tzinfo=pytz.UTC)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.