Django에서 날짜 범위별로 쿼리 객체를 어떻게 필터링합니까?


248

하나의 모델에 다음과 같은 필드가 있습니다.

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

이제 날짜 범위별로 개체를 필터링해야합니다.

어떻게 사이에 날짜있는 모든 개체를 필터링 할 1-Jan-2011과를 31-Jan-2011?

답변:


411

사용하다

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

또는 월 단위로 현명하게 필터링하려고하는 경우 :

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

편집하다

Bernhard Vallant가 말했듯이, 제외하는 쿼리 세트를 원하면 gt / lt (보다 큼 /보다 큼)를 사용하는 솔루션을specified range ends 고려해야 합니다.


date1의 데이터 유형은 무엇입니까? datetime 객체가 있습니다.
user469652

8
@dcordjer : __range또한 테두리 를 포함 한다고 말하면 sql 's와 같이 BETWEEN테두리를 포함하고 싶지 않다면 테두리를 포함하지 않으려면 내 gt / lt 솔루션과 함께 가야합니다 ...
Bernhard Vallant

이것은 본질적으로 어떤 순서로 정렬되어 있습니까? 그렇다면 어떤 주문입니까? 감사.
Richard Dunn

1
@RichardDunn 순서는 모델의 기본 순서를 기반으로하거나 위에서 언급 한 order_by에서 생성 QuerySet된 것 이상 을 사용 하는 경우를 기준으로합니다 filter. 나는 몇 년 동안 장고를 사용하지 않았습니다.
crodjer

date__range의 경우 다음 달 01을 입력해야합니다. 다음은 날짜의 00 : 00 : 00.0000으로 변환되는 문서화에 대한 링크입니다. 따라서 범위의 마지막 날은 포함되지 않습니다. docs.djangoproject.com/en/1.10/ref/models/querysets/#range 제가 사용이 경우 : date__range = "% S- % S-1"% (년, 월), "% S- % S- 1 "% (year, int (month) +1)]
SpiRail

195

djangofilterdatetime.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

1
crodjer에 비해이 방법을 사용하면 문자열 대신 datetime 객체를 전달할 수 있다는 이점이 있습니다.
Brian Kung

79

필터를 사용하여 장고 범위를 수행하는 경우 날짜 개체와 날짜 시간 개체의 차이점을 알아야합니다. __range는 날짜를 포함하지만 종료 날짜에 datetime 객체를 사용하는 경우 시간이 설정되지 않은 경우 해당 날짜의 항목이 포함되지 않습니다.

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

해당 날짜의 항목을 포함하여 시작 날짜부터 종료 날짜까지의 모든 항목을 반환합니다. 이것은 일주일에 미래에 항목을 반환하기 때문에 나쁜 예이지만 드리프트를 얻습니다.

    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()
Alex Spencer

19

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버리기 (그리고 혼란스러운) datetime객체 를 망칠 필요없이 날짜 인스턴스와 비교하는 것이 더 논리적 인 것처럼 보입니다 . 아래 설명에서 추가 설명을 참조하십시오.


1
절단 방법이 간단하게 멋진 Delorean 라이브러리가있다 : delorean.readthedocs.org/en/latest/quickstart.html#truncation
trojjer

@tojjer : 유망 해 보이지만 여기서 잘림 방법을 어떻게 사용합니까?
eugene

@eugene : 나는 몇 달이 지난 지금 바로 이것을 다시 탐구했으며, 결국이 상황에서 실제로 도움이되지 않는다는 점에서 옳습니다. 내가 생각할 수있는 유일한 방법은 원래의 응답에서 제안한 것입니다. 데이타 인스턴스에 대해 필터링 할 때 날짜 시간 모델 필드와 비교하기 위해 추가 '패딩'을 제공하는 것입니다. 위와 같이 datetime.combine 메소드를 통해 수행 할 수 있지만 범위의 시작 / 종료 날짜에 timedelta (days = 1)을 추가하여 불일치를 수용하는 것이 조금 더 간단하다는 것을 알았습니다. -문제에 따라.
trojjer

그래서 Example.objects.filter(created__range=[date(2014, 1, 1), date(2014, 2, 1)])에서 생성 된 개체를 포함하지 않을 date(2014, 2, 1)@cademan가 유용하게 설명 된대로. 그러나 하루를 추가하여 종료 날짜를 늘리면 누락 된 객체를 다루는 쿼리 세트가 표시됩니다 (그리고 date(2014, 2, 2)같은 기발한 이유로 생성 된 객체를 편리하게 생략합니다 ). 여기서 성가신 것은로 지정된 '수동'범위 created__gte ... created__lte=date(2014, 2, 1)가 작동하지 않는다는 것인데, 이는 직관적으로 반 직관적 인 IMHO입니다.
trojjer

1
@tojjer : datetime_field__range = [delorean.parse ( '2014-01-01'). date, delorean.parse ( '2014-02-01'). date] 저에게 효과적입니다
eugene

1

간단합니다

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

나를 위해 작동


3
이 명확성을 위해 noobs에 대한뿐만 아니라 나를 위해 일한 : (date__date = ...) 수단 ({whateverColumnTheDateIsCalled} __ 일)
라이언 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.