如何使用F()对象与Django ORM一起执行此操作?

时间:2012-09-17 10:10:02

标签: django datetime orm

我遇到了这样的模型:

class Task(models.Model):
    timespan = models.IntegerField(null=True, blank=True)

class Todo(models.Model):
    limitdate = models.DateTimeField(null=True, blank=True)
    task = models.ForeignKey(Task)

我需要提取所有Todos limitdate,其Task低于或等于今天的日期+相关today = datetime.datetime.now() Todo.objects.filter(limitdate__lte=today + F('task__timespan')) 模型中定义的时间跨度。

像(虚拟示例):

F()

现在,我可以通过循环执行此操作,但我正在寻找使用F()执行此操作的方法,但我找不到。

我开始怀疑我是否可以用extra做到这一点。也许我应该使用{{1}}?

请注意,我无需更改型号代码。

2 个答案:

答案 0 :(得分:5)

主要问题是DB不支持date + integer并且很难为date + integer::interval编写ORM查询,例如PostgreSQL,其中integer是{{1}的值列数,天数。

然而,作为
task_timespan等于
limitdate <= today + task__timespan

我们可以将查询转换为

limitdate - today <= task__timespan

因此SQL变得像Todo.objects.filter(task__timespan__gte=F('limitdate') - today).distinct(),它应该在PostgreSQL中工作,因为integer >= date - date输出date - date,可以与interval天计数进行比较。

在其他数据库中,例如SqLite,它很复杂,因为日期需要首先投放integer ...而且我认为你需要玩w julianday()甚至{{1}获取正确的SQL。

此外,正如Chris Pratt建议的那样,如果您可以在所有相关字段中使用时间戳,则查询任务可能会变得更容易,因为加减运算的限制较少。

P.S。我现在没有env验证它,你可以先试试。

答案 1 :(得分:2)

问题是数据库上没有TIMESPAN类型。因此,F无法返回您在此上下文中实际可以使用的内容。我不确定你在数据库中实际使用了哪种类型的字段,但我能想到的唯一方法是将时间跨度存储为由秒组成的整数,将其添加到“今天”作为时间戳,然后将其转换回日期时间,您可以使用该日期时间与limitdate进行比较。但是,我不确定Django是否会接受F这样复杂的逻辑。