从超级模式(棉花糖)继承 "exclude" 元参数

Inheriting "exclude" meta parameter from super schema (marshmallow)

我有一个对象层次结构和一个与之对应的模式层次结构。此层次结构中间级别的架构排除了特定的继承字段。我希望从它继承的模式将 "inherit" 这种排除,但如果他们在其 Meta classes:

中添加自己的排除字段,情况似乎并非如此
from marshmallow import fields
from marshmallow.schema import Schema


class AncestorSchema(Schema):
    a = fields.Str()
    b = fields.Str()


class IntermediateSchema(AncestorSchema):
    c = fields.Str()

    class Meta:
        exclude = ('b',)


class FinalSchema(IntermediateSchema):
    d = fields.Str()

    class Meta:
        exclude = ('c',)


value = dict(
    a="Field A",
    b="Field B",
    c="Field C",
    d="Field D"
)

print(IntermediateSchema().dump(value).data)

>>> {'c': 'Field C', 'a': 'Field A'}

print(FinalSchema().dump(value).data)

>>> {'d': 'Field D', 'a': 'Field A', 'b': 'Field B'}

在上面的示例中,FinalSchema 继承自 IntermediateSchema(不包括字段 b)并在其自身 Meta 中排除字段 c class。预期的行为是生成的架构将同时排除 bc,但实际上它仅排除 c.

当然可以手动包含超模式的排除字段继承模式的排除字段,但这不是继承的重点,而且很麻烦。

我想知道是否可以以优雅的方式实现所需的行为,或者模式继承的当前行为是否实际上是一个错误。

检查 marshmallow 的源代码表明至少部分支持从 superschemas 的元 classes 继承数据(即,ordered Meta 选项值是从 superschemas 继承的)。

您还需要为 Meta class 指定基础 class。您还需要使用某种反射从基础 class 获取值并附加到它。

from marshmallow import fields
from marshmallow.schema import Schema


class AncestorSchema(Schema):
    a = fields.Str()
    b = fields.Str()


class IntermediateSchema(AncestorSchema):
    c = fields.Str()

    class Meta:
        exclude = ('b',)


class FinalSchema(IntermediateSchema):
    d = fields.Str()

    def __init__(self, *args, **kwargs):
        self.opts.exclude += ('c',)
        super().__init__(*args, **kwargs)

其他答案无效,因为 self 未定义。我找到了一个有效的解决方案。

from marshmallow import fields
from marshmallow.schema import Schema


class AncestorSchema(Schema):
    a = fields.Str()
    b = fields.Str()


class IntermediateSchema(AncestorSchema):
    c = fields.Str()

    class Meta:
        exclude = ('b',)


class FinalSchema(IntermediateSchema):
    d = fields.Str()

    def __init__(self, *args, **kwargs):
        self.opts.exclude += ('c',)
        super().__init__(*args, **kwargs)