首页 > 解决方案 > 在 Schema 定义后注册一个 post_load 钩子?

问题描述

我正在尝试实现一个反序列化为 object的 Schema ,其中对象类在 Schema-definition 时是未知的。我会假设我可以post_load在运行时注册一个函数,但它似乎post_load适用于类方法。

似乎我可以通过以下任一方式使其工作:

由于这两个选项都有些hack-ish,是否有官方方法可以达到相同的结果?

标签: pythonserializationdeserializationmarshallingmarshmallow

解决方案


我认为您不需要元类。

使用只需要该类的后加载方法定义基本模式。

class CustomSchema(Schema):

    @post_load
    def make_obj(self, data):
        return self.OBJ_CLS(**data)

如果类在导入时已知(不是您的用例),这允许您通过仅提供类来分解实例化。已经不错了

class PetSchema(CustomSchema):

    OBJ_CLS = Pet

如果类在导入时未知,则可以在之后提供。

class PetSchema(CustomSchema):
    pass


PetSchema.OBJ_CLS = Pet

如果您在实例化之前需要更多处理,那么您可以make_obj在任何类中覆盖,如您在答案中所示。

class PetSchema(CustomSchema):
    def make_obj(self, data):
        data = my_func(data)
        return Pet(**data)

更一般地说,这种机制允许您在基本模式中定义挂钩。post_load这是克服棉花糖当前限制的好方法:可以按任意顺序执行多个方法这一事实。在基类中定义一个post_load方法,每个处理步骤都有一个钩子。(这个人为的例子并没有真正说明这一点。)

class CustomSchema(Schema):

    @post_load
    def post_load_steps(self, data):
        data = self.post_load_step_1(data)
        data = self.post_load_step_2(data)
        data = self.post_load_step_3(data)
        return data

    def post_load_step_1(self, data):
        return data

    def post_load_step_2(self, data):
        return data

    def post_load_step_3(self, data):
        return data


推荐阅读