我有一个简单的模型来描述任务和任务执行之间的时间段:
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 做同样的事情,以便我可以一次查询所有新的/过时的任务?
例如这显然行不通,但类似于:
Tasks.objects.filter(Q(last_check_timestamp__isnull=True) || Q(last_check_timestamp + datetime.timedelta(seconds=schedule__interval_seconds)))
请您参考如下方法:
我最近不得不做一个类似的查询。我希望使用 F() 来做到这一点对象,但我认为这是不可能的,因为 timedelta 依赖于 db 列(如果 schedule_interval_seconds 是一个常量,这是可能的)。
最后,我使用 ORM 和 extra() 进行了查询, 并为 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())"""
