Django中基于字段的动态范围滤波器

Django中基于字段的动态范围滤波器,django,datetime,django-queryset,Django,Datetime,Django Queryset,我对Django比较陌生,还不熟悉Django查询集。 我想根据基于字段的日期时间范围筛选查询集。 在MySQL中,我会这样做 WHERE (start_time < NOW() - INTERVAL duration MINUTE) 其中(开始时间

我对Django比较陌生,还不熟悉Django查询集。 我想根据基于字段的日期时间范围筛选查询集。 在MySQL中,我会这样做

WHERE (start_time < NOW() - INTERVAL duration MINUTE)
其中(开始时间
这里的开始时间是日期时间,持续时间是持续时间的整数,单位为分钟


我如何在Django中以可移植的方式执行此操作?我知道我可以一直使用它,但我更希望它能在MySQL和Sqlite3中工作。这些数据库管理器似乎不共享任何datetime函数

您可以在查询中使用“F”表达式来引用过滤器表达式中的模型字段(请参阅)

这意味着在过滤器中,对于任何特定行,都可以说“其中
time\u a
time\u b
之前”:

filter(time_a__lt=F('time_b')
但是,出现问题的原因是,
timedelta
不接受动态
F()
表达式。。。因此,似乎需要自定义SQL。但是,您可以在Django中对sqlite和mysql自动进行测试,以断言它在这两个方面都有效

同时,一个避免定制SQL的特别肮脏的解决方案是将
开始时间
转换为Unix时间,这使得数学计算变得简单

from calendar import timegm
from datetime import timedelta

from django.db import models
from django.db.models import F
from django.utils.timezone import now


class Journey(models.Model):
    name = models.CharField(max_length=64)
    start_time = models.IntegerField()
    duration_minutes = models.IntegerField()


def current_journeys():
    unow = timegm(now().utctimetuple())
    q = Journey.objects.filter(start_time__gt=unow-60*F('duration_minutes'))
    return q.all()

我们刚刚用django.test.TestCase测试了它,它可以与sqlite3和mysql引擎一起使用,但在我的例子中,它不是一个固定的范围。它取决于数据库中每行的持续时间字段。这就是为什么我明确说明了开始时间和持续时间类型。我可能必须以完全避免问题的方式解决我的问题,但是如果知道这是可能的,那就太好了。在我看来,如果每行都有
开始时间
持续时间
,你就可以很容易地计算出
结束时间
,并将其存储在模型中,那么你就有了一个非常容易过滤的字段,可以兼容不同的引擎。我不清楚
duration
是从每个实例内部提供的,而不是外部提供的。@Sten-Åke我现在更好地理解了你的问题,链接到了一个相关的问题,并用解决方案更新了我的答案。这是一个相关的问题: