在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来做同样的事情,这样我就可以一次性查询所有的新鲜和过期任务。
比如,这显然是行不通的,但类似这样的:
Tasks.objects.filter(Q(last_check_timestamp__isnull=True) || Q(last_check_timestamp + datetime.timedelta(seconds=schedule__interval_seconds)))
1 个回答
3
我最近也遇到了类似的查询需求。我原本希望能用F()
对象来实现,但我觉得这可能不行,因为时间差是依赖于数据库中的某个字段(如果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文档)。你可能需要根据不同的SQL版本进行调整。select_related
是必须的,这样Django才能连接到调度表。
上面的查询没有选择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())"""