如何使用 SQLAlchemy TypeDecorator 向列添加方法

Mup*_*sat 4 python sqlalchemy

我正在尝试向 ORM 类成员添加自定义方法,以使其处理与该成员相关的事物。尝试遵循文档

class EnhDateTime(types.TypeDecorator):
    impl = types.DateTime
    def foo(self):
        return "foo"

class MyDoc(Base):
     id = Column(Integer, primary_key=True,  autoincrement=False) 
     created = Column(EnhDateTime)

doc = session.query(MyDoc).filter_by(id=123).one()
Run Code Online (Sandbox Code Playgroud)

不幸的是,什么也没发生,成员仍然是 DateTime 类型:

type(doc.created)
Run Code Online (Sandbox Code Playgroud)

日期时间.日期时间

doc.created.foo()
Run Code Online (Sandbox Code Playgroud)

属性错误

Bla*_*ack 5

TypeDecorator 不是类型,它只是装饰类型,即它定义了在某些情况下调用的一些方法,例如当将值传递到数据库或从数据库传递值时。您需要实现process_bind_param()和两个方法process_result_value()。在那里,您可以将数据库中的值转换为您想要的值或从数据库中的值转换为您想要的值。

例如,请参阅TypeDecorator 配方部分中的 JSON 示例:

from sqlalchemy.types import TypeDecorator, VARCHAR
import json

class JSONEncodedDict(TypeDecorator):

    impl = VARCHAR

    def process_bind_param(self, value, dialect):
        if value is not None:
            value = json.dumps(value)

        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            value = json.loads(value)
        return value
Run Code Online (Sandbox Code Playgroud)

例子:

from datetime import datetime
from sqlalchemy.types import TypeDecorator, DATETIME

class _EnhDateTime(datetime):

    def foo(self):
        return 'foo'


class EnhDateTime(TypeDecorator):

    impl = DATETIME

    def process_result_value(self, value, dialect):
        if value is not None:
            value = _EnhDateTime(
                value.year, value.month, value.day, value.hour, value.minute,
                value.second, value.microsecond, value.tzinfo
            )
        return value
Run Code Online (Sandbox Code Playgroud)

我们不需要实现,process_bind_param()因为_EnhDateTime实例就是 datetime实例,所以默认的绑定处理器DATETIME应该可以实现。