如何编写 Django 查询并在 WHERE 子句中包含 PostGres 函数 (current_time)?

How do I write a Django query and include a PostGres function (current_time) in my WHERE clause?

我正在使用 Django、Python 3.7 和 PostGres 9.5。我想在 Django 中编写以下 WHERE 子句...

WHERE date_part('hour', current_time) = s.hour ...

所以在阅读其他一些文档时,我被引导相信我需要写一个 "Func" 在 运行 我的查询之前创建一个注释 ...

qset = ArticleStat.objects.annotate(
    hour_of_day=Func(
        'current_time',
        Value('hour'),
        function='date_part',
    )
).filter(hour_of_day=F("article__website__stats_per_hour__hour"))

但是,这会导致

Cannot resolve keyword 'current_time' into field. Choices are: article, article_id, elapsed_time_in_seconds, id, score

错误。似乎 Django 正在尝试将 "current_time" 视为我的 table 中的一个列,但我真的希望它被视为 PostGres 函数。我该怎么做?

更新 2:阅读您使用带注释的 hour_of_day 的过滤器子句,只需将子句翻转过来就会使一切变得容易得多,除非我忽略了某些东西:

hour = datetime.datetime.now().hour
qset = ArticleStat.objects.filter(article__website__stats_per_hour__hour=hour)

更新:比下面的双注解更简单的是获取 Python 中的当前时间(每个查询一次而不是每行一次)并将其传递给函数。您可能需要确保时区匹配。

import datetime
from django.db.models import DateTimeField
from django.db.models.expressions import Func, Value

current_time = datetime.datetime.now()
qset = Session.objects.annotate(
    hour_of_day=Func(
        Value('hour'),
        Value(current_time, output_field=DateTimeField()),
        function='date_part',
    )
)

一个简单的 hack 是使用两个注释来避免将数据库函数嵌套在另一个函数中(如果您足够认真的话,您可以使用从 Func 继承的自定义函数来实现):

from django.db.models import DateTimeField
from django.db.models.expressions import Func, Value

qset = MyModel.objects.annotate(
    current_time=Func(
        Value(0),
        function='current_time',
        output_field=DateTimeField()
    )).annotate(
    hour_of_day=Func(
        Value('hour'),
        F('current_time'),
        function='date_part',
    )
)