2014-02-13 5 views
1

나는 장고에서 날짜 시간을 필터링하여 aware of problems입니다. 그래서 원시 쿼리 세트를 빌드하는 것입니다.장고 필터 날짜를 연, 월, 일,시, 분으로 일

query = 'SELECT * FROM meteorological_data_base.meteorological_data' 

if year is not None: 
    query += ' WHERE EXTRACT(YEAR FROM date_time) = ' + year 
    if month is not None: 
     query += ' AND EXTRACT(MONTH FROM date_time) = ' + month 
     if day is not None: 
      query += ' AND EXTRACT(DAY FROM date_time) = ' + day 
      if hour is not None: 
       query += ' AND EXTRACT(HOUR FROM date_time) = ' + hour 
meteorological_data_list = MeteorologicalData.objects.raw(query) 

SQL 인젝션에 대해 알고 있습니다. 테스트 용으로 작성되었습니다. 문제는 Pagination 때문에 쿼리 세트가 필요하다는 것입니다. 지금은 this solution을 시도하고 난 그냥 연도 부분 지정하는 경우에만 작동 : 나는 또한 달에 전달하면

MeteorologicalData.objects.filter(date_time__year=2010) 

를, 그것은 빈 쿼리 세트 반환

MeteorologicalData.objects.filter(date_time__year=2010, date_time__month=1) 

것은 내가 장고 디버깅을 사용하고 있습니다으로 도구 모음 장고가 어떤 종류의 SQL 쿼리를 생성하는지 확인할 수 있습니다. 그리고 마지막 예제 (년과 월)에서는 다음과 같이 생성했습니다 :

SELECT COUNT(*) FROM `meteorological_data` WHERE (EXTRACT(MONTH FROM CONVERT_TZ(`meteorological_data`.`date_time`, 'UTC', 'Europe/Ljubljana')) = 1 AND `meteorological_data`.`date_time` BETWEEN '2009-12-31 23:00:00' and '2010-12-31 22:59:59') 

나는 이것을 mysql 콘솔에서 시도했지만 확실히 0 행을 반환합니다. CONVERT_TZ 명령을 제거한 경우 :

SELECT COUNT(*) FROM `meteorological_data` WHERE (EXTRACT(MONTH FROM `meteorological_data`.`date_time`) = 1 AND `meteorological_data`.`date_time` BETWEEN '2009-12-31 23:00:00' and '2010-12-31 22:59:59') 

정상적으로 작동합니다. 이제는 시간대를 인식하는 데 걸리는 시간을 사용하고 있습니다. 내 설정 구성 :

TIME_ZONE = 'Europe/Ljubljana' 
USE_TZ = True 

마지막 질문은 다음과 같습니다. 시간대를 인식하는 날짜 시간으로 변환하지 않는 필터 명령을 사용하는 방법. 데이터는 이미 UTC 형식으로 저장되어 있습니다.

편집 : 좋습니다, 이유는 missing TIMEZONE table in MySql입니다. 하지만 여전히 TIMEZONE으로 변환하지 않고 필터링하는 방법은 무엇입니까?

답변

0

USE_TZ 설정을 종료하면 어떻게됩니까? 또한 (매개 변수화 된 쿼리를 사용하도록 SQL을 정리한다고 가정하면) .raw() 메서드를 사용하여 RawQuerySet을 다시 얻을 수 있습니다.

EDIT : 쿼리 할 때 쿼리하는 데이터가 UTC이지만 문제가 사용중인 datetime이 아니라면 쿼리를 실행하기 전에 datetime을 UTC로 변환하지 않는 이유는 무엇입니까?

+0

USE_TZ 설정을 끄면 예상대로 작동합니다. 하지만 일부 다른 페이지에서는 시간대 인식 날짜 시간이 필요합니다. 코드 블록의 특정 스크립트에만 사용할 수 있도록 설정하려는 경우가 있습니다. –

+0

그냥 RawQuerySet을 시도했습니다. 문제는 메소드 len이나 count가 없다는 것입니다! Pagination 문서에서 :'Paginator에 list/tuple, Django QuerySet 또는 count() 또는 __len __() 메소드가있는 다른 객체를 지정할 수 있습니다. 전달 된 객체에 포함 된 객체 수를 결정할 때 Paginator는 먼저 count()를 호출 한 다음 전달 된 객체에 count() 메소드가없는 경우 len()을 사용하여 대체합니다. 이렇게하면 장고의 QuerySet과 같은 객체가 더 효율적인 count() 메소드를 사용할 수있게됩니다. ' –

+0

RawQuerySet의 결과를'list()'에 래핑 할 수 있지만 [메모리에 전체 결과 세트를로드합니다.] (http://stackoverflow.com/questions/2317452/django-count-rawqueryset) – Tom