【问题标题】:Django ORM: Filter on timedelta of Datetime fieldsDjango ORM:过滤日期时间字段的时间增量
【发布时间】:2015-12-19 15:24:17
【问题描述】:

我正在尝试根据两个DateTimeFields 的时间差来获取帖子,例如,发布后不到 10 分钟内被删除的帖子。

class Post(models.Model):
    ...
    time_posted = models.DateTimeField()
    time_deleted = models.DateTimeField(blank=True, null=True)

拿着上面的模型,我试过了;

from datetime import timedelta

Post.objects.exclude(deleted__isnull=True).annotate(
    delta=F('time_deleted') - F('time_posted')
).filter(delta__lt=timedelta(minutes=10))

并获得了TypeError: expected string or buffer。然后我认为这可能是类型的变化(DateTime 对象产生 Time 对象)所以我尝试使用ExpressionWrapper

Post.objects.exclude(deleted__isnull=True).annotate(
    delta=models.ExpressionWrapper(
        F('time_deleted') - F('time_posted'), 
        output_field=models.TimeField())
    ).filter(delta__gt=timedelta(minutes=10))

但这也导致了同样的异常。

非常感谢任何帮助。

编辑

根据@ivan 的建议,我尝试了DurationField()。我不再收到异常,但增量始终为 0

>>> post = Post.objects.exclude(deleted__isnull=True).annotate(
        delta=ExpressionWrapper(F('deleted') - F('time'), 
        output_field=DurationField())
    ).first()
>>> post.time_posted
datetime.datetime(2015, 8, 24, 13, 26, 50, 857326, tzinfo=<UTC>)
>>> post.time_deleted
datetime.datetime(2015, 8, 24, 13, 27, 30, 521569, tzinfo=<UTC>)
>>> post.delta
datetime.timedelta(0)

【问题讨论】:

  • 您是否尝试过使用models.DateTimeField() 作为输出字段?
  • @LaundroMat @omat 可能是models.DurationField
  • 是的,“DurationField”有效。非常感谢。

标签: django django-orm django-aggregation


【解决方案1】:

output_field kwarg 应该改为 DurationField,因为它在 Django 中存储 datetime.timedelta,而 TimeField 存储 datetime.time

但有一个警告:

DurationField 算术在大多数情况下都有效。但是,在 PostgreSQL 以外的所有数据库上,将 DurationField 的值与 DateTimeField 实例上的算术进行比较将无法按预期工作。

在 SQLite 后端中,DurationField 由存储微秒的bigint 表示:

class DatabaseWrapper(BaseDatabaseWrapper):
    vendor = 'sqlite'
    # ...
    data_types = {
        # ...
        'DecimalField': 'decimal',
        'DurationField': 'bigint',
        'FileField': 'varchar(%(max_length)s)',
        # ...
    }

因此,因为您使用的是 SQLite,所以您实际上需要 delta 是一个以微秒为单位的值。请参阅 this answer 以获取执行此操作的 Func

【讨论】:

  • 我不再收到异常,但增量始终为“0”。请在问题中查看我的编辑。谢谢。
  • 本地开发机器上的Sqlite。
  • 我将链接到您的案例。
猜你喜欢
  • 2021-10-30
  • 2015-03-06
  • 2022-08-22
  • 1970-01-01
  • 2019-11-20
  • 2020-11-27
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多