【问题标题】:Django ORM: How can I filter based on an annotation timedelta resultDjango ORM:如何根据注释 timedelta 结果进行过滤
【发布时间】: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 这也有效,谢谢

标签: django orm django-queryset


【解决方案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 对象)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 2011-03-31
    • 2018-08-26
    • 1970-01-01
    • 2021-05-25
    相关资源
    最近更新 更多