Django에서 DateTimeField의 날짜를 어떻게 필터링합니까?


173

DateTimeField날짜와 비교 를 필터링하려고 합니다. 내말은:

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

나는 시간을 고려하지 않고 "언제나"를 원하기 때문에 빈 쿼리 세트 목록을 대답으로 얻습니다.

Django 에서이 작업을 수행하는 쉬운 방법이 있습니까?

날짜 시간에 시간이 설정되어 00:00있습니다.


5
이것은 장고의 성가심 중 하나입니다. 이것이 간단하고 일반적인 유스 케이스라고 생각하면 이것을 달성하는 간단한 방법은 없습니다.
rubayeet

답변:


114

이러한 조회는 django.views.generic.date_based다음과 같이 구현 됩니다.

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

매우 장황하기 때문에 __date연산자를 사용하여 구문을 향상시킬 계획이 있습니다 . 자세한 내용은 " # 9596 DateTimeField와 날짜를 비교하는 것이 너무 어렵다 "를 확인하십시오.


4
범위와 함께 사용 : Q(created__gte=datetime.combine(created_value, time.min))
Dingo

10
그것이 장고 1.9에 도착할 것
amjoconn

14
Django 1.9의 새로운 기능 :Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Non

102
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 객체를 생성하므로 데이터베이스의 시간이 일치하지 않으므로 작동하지 않습니다.


답을 위해 thx! 첫 번째 대안은 datetimefields와 함께 작동하지 않습니다. 두 번째 대안은 작동합니다;). 누군가 다른 방법을 알고 있다면 대답하십시오
Xidobix

docs.python.org/library/datetime.html#datetime-objects datetime 모듈 hrs, mins, secs에서 datetime ()을 사용하는 것은 선택 사항입니다. 두 번째는 vars가 교체 된 작업 프로젝트에서 나온 것입니다. 올바른 문서를 볼 수 있습니다
zalew

나는 그것이 선택적이라는 것을 안다. 문제는 내 datetimefield에 시간이 설정되어 있고 00:00이 아니라는 것이다.
Xidobix

"첫 번째 대안은 datetimefields와 함께 작동하지 않습니다." datetime.datetime ()이 datetime 객체를 반환하므로 djangoproject.com/documentation/0.96/models/basic 모델 정의 및 예를 확인하십시오. pub_date = models.DateTimeField () pub_date = datetime (2005, 7, 30)
zalew

"선택적이라는 것을 알고 있습니다. 문제는 내 datetimefield에 시간이 설정되어 있고 00:00이 아니라는 것입니다."아, 이제 알 수 있습니다. 예, 시간 인수가 없으면 00으로 설정되므로 반환하지 않습니다 :)
zalew

88

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

포함 이 더 빠른 것 같습니다.


이 솔루션이 가장 최신 것 같습니다. contains해결책을 시도 할 때 다음과 같은 오류 메시지가 표시 되기 때문에 4 개의 upvotes가 있다는 것에 놀랐습니다 .Unable to get repr for <class 'django.db.models.query.QuerySet'>
Houman

오늘 결과를 다시 확인하고 업데이트했는데 __contains필터로 인한 오류가 아닌 것 같습니다 . 그러나 문제가 발생 하면를 사용 하는 django docs 예제 를 사용해보십시오 __gte.
Moreno

4
__contains 메소드는 나에게 잘 작동합니다. 성능 비교를 제공하기 때문에 이것이 가장 좋은 대답이라고 생각합니다. 나는 둘 이상의 투표를했지만 더 많은 투표를하지 않은 것에 놀랐습니다.
RobotHumans

나는 startswith해결책을 좋아한다 ..
파 411 3

46

이제 Django에는 개발 버전의 날짜에 대해 datetime 객체를 쿼리하는 __date queryset 필터가 있습니다. 따라서 곧 1.9에서 사용할 수 있습니다.



최고의 답변, 최신 Django 버전에 유효
serfer2

내가 장고 1.11에있어 :(이 나를 위해 일을하지 않는, 아무 생각 왜 내 정확한 예외는 없다 : NotImplementedError : basedatabaseoperations의 서브 클래스는 datetime_cast_date () 메소드를 요구할 수있다
AbdurRehman 칸

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

위는 내가 사용한 것입니다. 작동 할뿐만 아니라 고유 한 논리적 백업도 있습니다.


3
다른 답변보다 훨씬 낫습니다. 감사합니다!
Kin

sssss-shazam! 💯
dps

30

Django 1.9 __date부터는 datetime 객체를 사용하는 방법이 있습니다.

예를 들면 다음과 같습니다. MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))


27

이것은 __year, __month 및 __day를 사용하는 것과 동일한 결과를 생성하며 저에게 효과적입니다.

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

19
이것은 날짜 객체를 문자열로 바꾸고 날짜의 문자열 비교를 수행하므로 db가 전체 테이블 스캔을 수행하도록합니다. 큰 테이블에 대 한이 하나는 성능을 죽
yilmazhuseyin

8

active_on이 날짜 객체라고 가정하고 1 일 단위로 증가시킨 다음 범위를 수행하십시오.

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

2

흥미로운 기술이 있습니다. MySQL에서 Django로 구현 된 startswith 프로 시저를 활용하여 날짜 만 통해 날짜 시간 만 조회 한 결과를 얻었습니다. 기본적으로 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가 해결책을 찾을 때까지 이것은 모두를 도울 것입니다!


자, 이것은 위의 mhost 및 kettlehell과 동일한 대답으로 보이지만 백엔드에서 발생하는 상황에 대한 자세한 설명이 있습니다. 적어도 datetime의 date () 속성과 함께 contains 또는 starts with를 사용해야 할 이유가 있습니다!
bbengfort

2

Django ORM의 날짜 및 날짜 시간 비교 : 여기에 이것을 다루는 환상적인 블로그 게시물이 있습니다.

Django> 1.7, <1.9에 게시 된 최상의 솔루션은 변환을 등록하는 것입니다.

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 () 함수가 없다고 믿습니다. 따라서이 간단한 구현은 반드시 다소 백엔드에 의존하는 것처럼 보입니다.


이 MySQL 특정입니까? 수업 이름 선택에 대해 궁금해합니다.
Binoj David

@BinojDavid 네, 백엔드에 의존합니다
Dan Gayle

Django 1.8 및 PostgreSQL 9.6.6을 사용하여 테스트했으며 완벽하게 작동합니다. 실제로 PostgreSQL을 사용하면 다음 구문을 사용할 수도 있습니다.return '{}::date'.format(lhs), params
michal-michalak

1

흠 .. 내 솔루션이 작동 중입니다.

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


0

장고 1.7.6에서는 다음과 같이 작동합니다.

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

2
정확한 날짜를 찾고있는 경우에만 사용할 수 __lte있으며 예를 들어 사용할 수 없습니다 .
guival

-1

Django Documentation 기사를 참조하십시오

ur_data_model.objects.filter(ur_date_field__gte=datetime(2009, 8, 22), ur_date_field__lt=datetime(2009, 8, 23))

5
django 문서에서 datetimefiled 시간이 00:00이기 때문에 작동합니다.
Xidobix
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.