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查询如何注释是不是存在多级外键层次结构