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

e-s*_*tis 6 django orm datetime

我遇到了这样的模型:

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)
Run Code Online (Sandbox Code Playgroud)

我需要提取所有Todoslimitdate低于或等于今天的日期+的相关定义的时间跨度Task模型.

像(虚拟例子):

today = datetime.datetime.now()
Todo.objects.filter(limitdate__lte=today + F('task__timespan'))
Run Code Online (Sandbox Code Playgroud)

现在,我可以通过循环来做到这一点,但我正在寻找一种方法来实现它F(),我找不到一个.

我开始怀疑自己是否可以这样做F().也许我应该用extra

请注意,我没有更改模型代码的奢侈.

okm*_*okm 6

主要问题是DB不支持date + integer并且难以编写ORM查询date + integer::interval,例如,对于PostgreSQL,列integer的值task_timespan是以天数计算的.

但是,
limitdate <= today + task__timespan等于
limitdate - today <= task__timespan

我们可以将查询转换为

Todo.objects.filter(task__timespan__gte=F('limitdate') - today).distinct()

因此SQL变得类似integer >= date - date,应该在PostgreSQL中工作,因为date - date输出interval可以与integer天数进行比较.

在其他数据库中,例如SqLite,它很复杂,因为日期需要首先投射julianday()...而且我认为你需要玩w/extra()甚至raw()获得正确的SQL.

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

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


Chr*_*att 2

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