Как мне написать запрос Django и включить функцию PostGres (current_time) в мое предложение WHERE? - PullRequest
0 голосов
/ 25 марта 2019

Я использую Django, Python 3.7 и PostGres 9.5.Я хочу написать следующее предложение WHERE в Django ...

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» как столбец из моей таблицы, но я действительно хочу, чтобы он рассматривался как функция PostGres.Как мне это сделать?

1 Ответ

0 голосов
/ 25 марта 2019

Обновление 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',
    )
)

Простым хаком было бы использование двух аннотаций, чтобы избежать вложения функции базы данных в другую (что вы, вероятно, можете сделать с пользовательской функцией, подклассом которой является 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',
    )
)
...