0

我正在研究 SQLAlchemy 中的一个项目。我有Command一个类,它具有称为toBinArray()and的自定义序列化/反序列化方法fromBinArray(bytes)。我将它用于 TCP 通信(我不想使用 pickle,因为我的函数会创建较小的输出)。

Command有几个子类,我们称它们CommandGet为 ,CommandSet等。它们有额外的方法和属性以及序列化方法重新定义以跟踪它们自己的属性。我使用polymorhic_identity机制将它们都放在一张桌子上。

问题是有很多子类,每个子类都有不同的属性。我之前已经为它们中的每一个编写了映射,但是这种方式表有大量的列。

我想编写一种机制,在每次写入数据库之前将self.toBinArray()每个实例序列化(使用)属性(存储在二进制列中),并在每次从数据库加载实例后加载(使用)属性。self._bin_arrayself.fromBinArray(value)

我已经找到了部分问题的答案:我可以用装饰器调用self.fromBinArray(self._bin_array)函数。@orm.reconstructor它被每个Command子类继承并执行正确继承的fromBinArray(). 我的问题是如何在写入数据库时​​自动序列化(我知道我可以手动设置self._bin_array,但这很麻烦)?

PS我的部分代码,我的主要课程:

class Command(Base):
    __tablename__ = "commands"
    dbid = Column(Integer, Sequence("commands_seq"), primary_key = True)
    cmd_id = Column(SmallInteger)
    instance_dbid =  Column(Integer, ForeignKey("instances.dbid"))
    type = Column(String(20))
    _bin_array = Column(Binary)

    __mapper_args__ = {
    "polymorphic_on" : type,
    "polymorphic_identity" : "Command",
    }

    @orm.reconstructor
    def init_on_load(self):
        self.fromBinArray(self._bin_array)

    def fromBinArray(self, b):
        (...)
    def toBinArray(self):
        (...)

编辑:我找到了解决方案(下面的答案),但是还有其他解决方案吗?也许一些在类体内插入事件监听功能的捷径?

4

1 回答 1

0

看起来解决方案比我预期的要简单——您需要为before_insert(和/或before_update事件)使用事件侦听器。我发现信息(来源

重构器() 是进入更大的“实例级”事件系统的快捷方式,可以使用事件 API 订阅该事件 - 有关这些事件的完整 API 描述,请参阅 InstanceEvents。

这给了我线索:

@event.listens_for(Command, 'before_insert', propagate = True)
def serialize_before_insert(mapper, connection, target):
    print("serialize_before_insert")
    target._bin_array = target.toBinArray()

您也可以使用event.listen()函数将事件监听器绑定到实例,但我个人更喜欢装饰器方式。在声明中添加非常重要,propagate = True)以便子类可以继承侦听器!

于 2013-08-11T18:56:40.767 回答