如何在 Django F 表达式中将日期和时间字段合并到 DateTime 字段中

Posted

技术标签:

【中文标题】如何在 Django F 表达式中将日期和时间字段合并到 DateTime 字段中【英文标题】:How to Combine Date and Time Fields into DateTime Field in Django F Expression 【发布时间】:2019-10-31 01:39:31 【问题描述】:

我必须得到两个datetime 字段的区别,但一个是纯日期时间字段,另一个是日期和时间的组合。 我试过这个:

    qs = Foo.objects.filter(
        bar__baz_id=self.kwargs['baz_pk'],
    )
    start_datetime = ExpressionWrapper((F('x__date') + F('x__start')), output_field=DateTimeField())
    qs = qs.annotate(start_datetime=start_datetime)
    before_start_wrapper = ExpressionWrapper(
        F('start') - F('start_datetime'),   # 'start' is datetime field on Foo, start_datetime is annotated field on Foo
        output_field=DateTimeField()
    )
    before_start = Extract(before_start_wrapper, 'epoch')
    qs = qs.annotate(before_start=before_start/3600)

这也不行;

    qs = Foo.objects.filter(
        bar__baz_id=self.kwargs['baz_pk'],
    )
    start_datetime = F('x__date') + F('x__start')

    before_start_wrapper = ExpressionWrapper(
        F('start') - F(start_datetime), # 'start' is datetime field on Foo, start_datetime is combined F expression
        output_field=DateTimeField()
    )
    before_start = Extract(before_start_wrapper, 'epoch')
    qs = qs.annotate(before_start=before_start/3600)

django 的作用如下:

...(EXTRACT('epoch' FROM "foo".came" - ("db_shift"."date" + "db_shift"."start")) AT TIME ZONE) /3600 AS ...

我期待的是:

...(EXTRACT('epoch' FROM "foo".came" - ("db_shift"."date" + "db_shift"."start")AT TIME ZONE)) / 3600 AS ...

有人可以提供 Django ORM 的解决方案吗?我知道我可以运行原始查询,但想看看是否有办法用 Django ORM 做同样的事情?

谢谢。

【问题讨论】:

您在其他模型中没有使用DateTimeField 有什么原因吗? 不,但我必须做一个大的改变,现在我想通过结合日期和时间字段来处理它 @wencakisa 你也可以回答这个问题吗? 【参考方案1】:

我已经解决了这个问题并得到了答案。只需要ExpressionWrapperoutput 参数中的DurationField() 而不是DateTimeField()。代码如下:

qs = Foo.objects.filter(
    bar__baz_id=self.kwargs['baz_pk'],
)
start_datetime = F('x__date') + F('x__start')

before_start_wrapper = ExpressionWrapper(
    F('start') - F(start_datetime), # 'start' is datetime field on Foo, start_datetime is combined F expression
    output_field=DurationField()
)
before_start = Extract(before_start_wrapper, 'epoch')
qs = qs.annotate(before_start=before_start/3600)

这样我就可以解决我之前遇到的问题。这可能对其他人有帮助。

【讨论】:

以上是关于如何在 Django F 表达式中将日期和时间字段合并到 DateTime 字段中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中将日期时间转换为毫秒?

如何在 django 中将一个表单字段拆分为模型的多个字段?

日期时间对象上的 Django F 表达式

Django - 在模板中呈现日期字段

如何在 Django Rest Framework 中将当前用户设置为用户字段?

Django F 表达式加入字段