DjangoORM : Resolve F Expression in Custom DB Function

标签 django django-queryset django-orm django-1.10 django-postgresql

我正在尝试在 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/

相关文章:

django - Django queryset values_list是否返回列表对象?

jquery - 如何获取具有脆格式的 div 的 'hidden' 属性?

python - 是否检查相关对象

django - django 中的相关模型查询

mysql - 如何在 Django 模型字段中强制执行 char(N) 数据类型而不是 varchar(N)

Django:查找多对多关系中的所有值,其中相关集的所有元素都符合特定条件

python - 如何将 Python 中小数的 "trim"有效数字仅转换为非零值?

django - 在django中,models.ImageField默认采用哪种格式

sql - Django annotate() 多次导致错误答案

django - 使用查询来匹配对象,然后通过外键获取关联的所有对象