2

我正在尝试在 sqlalchemy 中实现对相对日期范围(月、年)的基本支持。使用 postgres 作为数据库,我认为子类化 sqlalchemy.dialects.postgres.Interval 并将返回的 python 类型更改为 dateutil.relativedelta.relativedelta 将是最好/最快的方法。

from sqlalchemy import types
from sqlalchemy.dialects.postgres import INTERVAL
from dateutil import relativedelta

class DateInterval(INTERVAL):
    def result_processor(self, dialect, coltype):
        def process(value):
            return value
        return process

@property
def python_type(self):
    return relativedelta.relativedelta


class MyInterval(types.TypeDecorator):
    impl = DateInterval

    def process_bind_param(self, value, dialect):
        result = ''
        for attr in ["years", "months", "days", "hours", "minutes", "seconds"]:
            tempvalue = getattr(value, attr)
            if tempvalue:
                result += "%s %s " % (tempvalue, attr)
        return result

    def process_result_value(self, value, engine):
        return value

    @property
    def python_type(self):
        return relativedelta.relativedelta

刷新到数据库按预期工作,process_bind_param 方法有效。之后取它,不会。result_processor 方法的 process 函数中的 value 参数已经是 timedelta 对象。在哪里挂钩,将原始值处理为 relativedelta 对象?或者,还有更好的方法?

4

1 回答 1

1

psycopg2 正在返回那些时间增量。如果你想拦截这些,你需要在 psycopg2 级别增加东西:http: //initd.org/psycopg/docs/advanced.html#type-casting-of-sql-types-into-python-objects 也许您可以使用 new_type() 来规避 psycopg2 的 INTERVAL 对象的默认类型转换器。

第一步是从普通的 psycopg2 连接/光标中获取原始值,以确保您在该级别具有控制权。

然后当你弄清楚如何得到它时,你可以拦截新创建的 psycopg2 连接对象并在连接事件中设置你想要的适配器。

于 2013-10-10T18:49:58.847 回答