쿼리

2011-10-19 1 views
2

내가 작업하고 작업의 실행 사이의 기간을 설명하는 간단한 모델을 장고 ORM에 시간 차이 만료 :쿼리

내가 작업이 장고의 ORM을 사용하여 조회 할 수 있도록하려면
class Task(models.Model): 
    last_check_timestamp = models.DateTimeField(blank=True, null=True, db_index=True) 

class TaskSchedule(models.Model): 
    task = models.OneToOneField(Task, blank=False, null=False, related_name='schedule') 
    interval_seconds = models.IntegerField(blank=False, null=False) 

신선하고 낡은 것, 즉 일정에 따라 운영 될 예정인 것을 의미합니다.

나는 현재를 통해 ORM없이 특정 레코드에 대한이 계산 해요 :

import datetime 
task = Task.objects.get(id=123) 
fresh = task.last_check_timestamp is not None and datetime.datetime.now() < (task.last_check_timestamp + datetime.timedelta(seconds=task.schedule.interval_seconds)) 

내가 장고의 ORM과 동등 할 것이다, 그래서 한 번에 모든 신선한/오래된 작업을 조회 할 수 있습니까?

이것은 분명히 작동하지 않지만 다음과 같은 것입니다 :

Tasks.objects.filter(Q(last_check_timestamp__isnull=True) || Q(last_check_timestamp + datetime.timedelta(seconds=schedule__interval_seconds))) 

답변

3

최근 비슷한 쿼리를 수행해야했습니다. 내가 F() 개체를 사용하여 그것을 바라고 있었지만 timedelta가 db 열에 의존하기 때문에 가능하지 않다고 생각합니다 (schedule_interval_seconds이 상수 일 경우 가능합니다).

결국 나는 extra()과 ORM을 사용하여 쿼리를 작성하고 where 절에 대해 SQL을 작성했습니다.

sql = "DATE_ADD(last_check_timestamp, INTERVAL schedule.interval_seconds SECOND) < DATE(NOW())" 
Tasks.objects.filter(Q(last_check_timestamp__isnull=True) || Q(last_check_timestamp + datetime.timedelta(seconds=schedule__interval_seconds))) 
tasks = Task.object.select_related('schedule').extra(where=[sql,] 

이것은 DATE_ADD 함수 (MySQL docs)를 사용한다. 다른 SQL 유형을 조정해야 할 수도 있습니다. Django가 schedule 테이블에 조인을 수행하려면 select_related이 필요합니다.

위는 last_check_timestamp이 null 인 작업을 선택하지 않습니다. extra()Q 개체를 결합하여 사용할 수는 없지만 SQL 문을 확장 할 수는 있습니다.

sql = """last_check_timestamp is NULL or DATE_ADD(last_check_timestamp, INTERVAL schedule.interval_seconds SECOND) < DATE(NOW())""" 
+0

흥미 롭군요. 내가 고려하고있는 또 다른 솔루션은 단순히 다음 실행의 날짜 시간을 구체화하여 timedelta를 제거하는 것입니다. 그리고 그 구체화 된 datetime으로 필터링합니다. – Cerin