我有一个简单的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中,我需要能够转储和加载此模型的稍微不同的变体:
GET /reports
)时,我要转储上述所有字段。GET /reports/1
)时,我想转储所有这些数据以及所有关联关系,例如Sample
表中的关联sample
对象(一个报告包含许多示例)POST /reports
)时,我希望用户提供除report_id
(将生成),report_hash
和{{1}之外的所有报告字段。 }(将在现场进行计算),并且我希望他们在其上载中包括所有关联的uploaded_at
对象。如何合理维护此架构的3个(或更多)版本?我应该:
Sample
子类?例如ModelSchema
,AggregateReportSchema
和SingleReportSchema
?UploadReportSchema
包含该模式中我可能想要的所有字段,然后使用ModelSchema
自变量in the constructor即时从中减去字段?例如exclude
? ReportSchema(exclude=[])
,其他模式对此进行子类化以添加其他字段(例如class ReportBaseSchema(ModelSchema)
)?答案 0 :(得分:0)
问了这个问题,我已经用棉花糖做了很多工作,希望我能有所解释。
我的经验法则是:尽可能多地使用模式构造函数(选项#2),并且在绝对必要时仅求助于继承(选项#3)。请使用选项#1,因为这将导致不必要的重复代码。
架构构造器方法很棒,因为:
only
,exclude
,partial
和unknown
参数使您有足够的能力自定义单个模式(see the documentation) include_data
,它使您可以控制为每个相关资源返回的数据量我的原始帖子是使用架构构造函数就足够了。您首先应该定义一个包含所有可能相关字段的架构,包括可能是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())