Skip to main content
 首页 » 编程设计

python之Django ORM查询过期时间差

2024年08月30日22lexus

我有一个简单的模型来描述任务和任务执行之间的时间段:

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())"""