gpt4 book ai didi

DjangoORM : Resolve F Expression in Custom DB Function

转载 作者:行者123 更新时间:2023-12-02 20:48:08 26 4
gpt4 key购买 nike

我正在尝试在 Django 中编写一个自定义 PostgreSQL 函数,它将日期时间强制转换为查询集中的指定时区。我对 db 函数的第一次传递看起来像这样:

from django.db.models.expressions import Func

class DateTimeInTimezone(Func):
template="%(expressions)s AT TIME ZONE %(tz_info)s"

此函数适用于我将时区字符串直接传递给函数的简单情况,如下所示:

MyModel.objects.filter(timefield__gte=DateTimeInTimezone(Now(), tz_info='EST'))

然而,它在更复杂的情况下不起作用,在这种情况下,时区是在模型的某个字段上定义的。考虑以下人为的示例:

class User(models.Model):
time_zone = models.CharField()

class Meeting(models.Model):
users = models.ManyToManyField(User, related_name='meetings')
start_time = models.DateTimeField() # in UTC
end_time = models.DateTimeField() # in UTC

要回答“哪些用户将在本地时间今天中午 12 点参加 session ?”这个问题,我需要这个查询集的一些变体:

noon_utc = ...
User.objects.filter(
meetings__start_time__lte=DateTimeInTimezone(noon_utc, tz_info=F('time_zone')),
meetings__end_time__gt=DateTimeInTimezone(noon_utc, tz_info=F('time_zone'))
)

然而,正如目前所写,DateTimeInTimezone 将简单地将字符串 F('time_zone') 注入(inject)到 sql 而不是解析该字段。

是否可以添加对 F Expressions 的支持到这个功能?我应该考虑其他方法吗?

最佳答案

使用 参数 arg_joiner 可以实现一个简单的解决方案:

class DateTimeInTimezone(Func):
function = ''
arg_joiner = ' AT TIME ZONE '

def __init__(self, timestamp, tz_info):
super(DateTimeInTimezone, self).__init__(timestamp, tz_info)

__init__ 方法仅用于参数名称清晰的可读性目的。如果参数由 __init__ 声明,则 arity 并不重要。

如果可读性不重要,oneliner 函数对于快速开发很有用:

...filter(
meetings__start_time__lte=Func(noon_utc, tz_info=F('time_zone'), arg_joiner=' AT TIME ZONE ', function=''),
)

已验证:

>>> qs = User.objects.filter(...)
>>> print(str(qs.query))
SELECT ... WHERE ("app_meeting"."start_time" <= ((2017-10-03 08:18:12.663640 AT TIME ZONE "app_user"."time_zone")) AND ...)

关于DjangoORM : Resolve F Expression in Custom DB Function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43397578/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com