在django使用F()和timedelta进行查询

rma*_*oft 9 django orm

我有以下型号:

class Process(models.Model):
  title = models.Charfield(max_length=255)
  date_up = models.DateTimeField(auto_now_add=True)
  days_activation = models.PositiveSmallIntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)

现在我需要Process根据它们的值来查询已过期的所有对象days_activation.

我试过了

from datetime import datetime, timedelta

Process.objects.filter(date_up__lte=datetime.now()-timedelta(days=F('days_activation')))
Run Code Online (Sandbox Code Playgroud)

并收到以下错误消息:

TypeError:timedelta days组件的不支持类型:F

我当然可以用Python做到这一点:

filter (lambda x: x.date_up<=datetime.now() - timedelta(days=x.days_activation), 
        Process.objects.all ()), 
Run Code Online (Sandbox Code Playgroud)

但我真的需要制作一个django.db.models.query.QuerySet.

Lut*_*elt 6

7 天 == 1 天 * 7

F是深黑色的姜戈魔法,遇到它的物体必须属于适当的魔法阵才能处理它。

就您而言,django.db.models.query.filter知道F,但datetime.timedelta不知道。因此,您需要将 排除F在参数列表之外timedelta。幸运的是, 的乘法timedelta * int受 的支持F,因此以下代码可以工作:

Process.objects.filter(date_up__lte=datetime.now()-timedelta(days=1)*F('days_activation'))
Run Code Online (Sandbox Code Playgroud)

事实证明,这适用于 PostgreSQL,但不适用于 SQlite (Django 1.11 仅支持+-for timedelta,可能是因为相应的 SQlite 限制)。


Gre*_*hov 2

您正在混合两个层:运行时层和数据库层。F函数只是一个帮助器,它允许您使用 django ORM 构建稍微复杂的查询。您正在一起使用timedeltaF,并期望 django ORM 能够足够智能地将这些内容转换为原始 SQL,但正如我所见,它不能。也许我错了,不了解 django ORM。

无论如何,您可以使用额外的额外内容重写 ORM 调用并使用等于datetime.now()和的本机 SQL 函数手动构建 WHERE 子句timedelta