Django ORM:如何根据注释 timedelta 结果进行过滤

Posted

技术标签:

【中文标题】Django ORM:如何根据注释 timedelta 结果进行过滤【英文标题】:Django ORM: How can I filter based on an annotation timedelta result 【发布时间】:2018-11-03 12:33:35 【问题描述】:

我有一个这样的模型:

class Interval(models.Model):
   start = models.Datetime()
   end = models.Datetime(null=True)

我想查询大于 5 分钟的所有时间间隔。 我能做到intervals=Interval.objects.exclude(end=None).annotate(d=models.F("end")-models.F("start"))

当我做 intervals[0].d 时,我有间隔,这是正确的。现在我只想得到 d 大于 5 分钟的条目作为结果。

我尝试了intervals=Interval.objects.exclude(end=None).annotate(d=models.F("end")-models.F("start")).filter(d__gt=timedelta(0, 300)),但收到以下错误:TypeError: expected string or bytes-like object。它尝试将 timedelta 与日期时间的正则表达式匹配。 `

有什么想法吗?

提前致谢

【问题讨论】:

.filter(end__lte=models.F("start")+timedelta(seconds=300))。像这样? @duduklein:你可能需要指定注解是DurationField @itzMEonTV 这也有效,谢谢 【参考方案1】:

我认为问题在于您必须将注释列的类型指定为 Django 为DurationField。所以你可以这样写:

from datetime import timedelta
from django.db.models import ExpressionWrapper, F, DurationField

delta = ExpressionWrapper(F("end")-F("start"), DurationField())

intervals = (Interval.objects.exclude(end=None)
                             .annotate(d=delta)
                             .filter(d__gt=timedelta(0, 300)))

这将构造如下查询:

SELECT id, start, end TIMESTAMPDIFF(MICROSECOND, start, end) AS `d`
FROM interval
WHERE TIMESTAMPDIFF(MICROSECOND, start, end) > 300000000

但是我们在这里给 Django 如何解释d 字段(作为DurationField)的提示,以及如何“序列化timedelta 对象)。

【讨论】:

以上是关于Django ORM:如何根据注释 timedelta 结果进行过滤的主要内容,如果未能解决你的问题,请参考以下文章

使用Django ORM查询如何注释是不是存在多级外键层次结构

如何使用 Django ORM 将注释字符串转换为布尔值

prefetch_related 上的 Django ORM 注释

复杂的 Django ORM 注释和聚合

在 django orm 中对多个注释求和

通过 Django ORM 重命名嵌套注释字段