处理棉花糖模式的多个变体

Handling multiple variants of a marshmallow schema

我有一个简单的 Flask-SQLAlchemy 模型,我正在为它编写一个 REST API:

class Report(db.Model, CRUDMixin):
    report_id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.user_id'), index=True)
    report_hash = Column(Unicode, index=True, unique=True)
    created_at = Column(DateTime, nullable=False, default=dt.datetime.utcnow)
    uploaded_at = Column(DateTime, nullable=False, default=dt.datetime.utcnow)

然后我有对应的Marshmallow-SQLAlchemy模式:

class ReportSchema(ModelSchema):
    class Meta:
        model = Report

但是,在我休息时 API,我需要能够转储和加载此模型的稍微不同的变体:

我怎样才能合理地维护这个模式的 3 个(或更多)版本?我应该:

自问这个问题以来,我已经使用 Marshmallow 做了很多工作,所以希望我能解释一下。

我的经验法则是:尽可能多地使用架构构造函数(选项 #2),只有在绝对必要时才求助于继承(选项 #3)。 切勿使用选项 #1,因为这会导致不必要的重复代码。

模式构造方法很棒,因为:

  • 你写的代码最少
  • 您永远不必重复逻辑(例如验证)
  • 架构构造函数的 onlyexcludepartialunknown 参数为您提供了足够的能力来自定义各个架构(see the documentation)
  • 架构子类可以向架构构造函数添加额外的设置。例如 marshmallow-jsonapi addds include_data,它可以让您控制每个相关资源 return 的数据量

我原来的post是使用schema constructor就够了的情况。您应该首先定义一个包含所有可能相关字段的模式,包括可能是 Nested 字段的关系。然后,如果有时您不想在响应中包含相关资源或多余字段,您可以在该视图方法中简单地使用 Report(exclude=['some', 'fields']).dump()

但是,我遇到的一个更适合使用继承的例子是当我为我生成的某些图的参数建模时。在这里,我想要传递到底层绘图库的一般参数,但我希望子模式改进模式并使用更具体的验证:

class PlotSchema(Schema):
    """
    Data that can be used to generate a plot
    """
    id = f.String(dump_only=True)
    type = f.String()
    x = f.List(f.Raw())
    y = f.List(f.Raw())
    text = f.List(f.Raw())
    hoverinfo = f.Str()


class TrendSchema(PlotSchema):
    """
    Data that can be used to generate a trend plot
    """
    x = f.List(f.DateTime())
    y = f.List(f.Number())