6

我遇到了这样的模型:

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

请注意,我没有更改型号代码的奢侈。

4

2 回答 2

6

主要问题是数据库不支持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来验证,你可以先试试。

于 2012-09-17T15:34:31.640 回答
2

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

于 2012-09-17T14:36:44.793 回答