查询Django ORM中的过期时差

时间:2011-10-19 16:42:24

标签: python django django-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)

我希望能够使用Django的ORM查询哪些任务是新鲜的,哪些是陈旧的,这意味着那些将根据他们的日程安排运行。

我正在为没有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))

我如何使用Django的ORM进行等效操作,这样我就可以一次查询所有新鲜/陈旧的任务?

e.g。这显然不起作用,但是像:

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

1 个答案:

答案 0 :(得分: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进行调整。 select_related是必需的,以便Django连接到计划表。

上面没有选择last_check_timestamp为空的任务。我认为您不能使用extra()Q对象的组合,但您可以扩展SQL语句。

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