问题
使用 Marshmallow 序列化平面结构的 SQLAlchemy 对象时如何将字段组合在一起而不更改后台的平面数据结构?
例子
假设 Flask 应用程序中有一个 SQLAlchemy 模型,如下所示:
from app import db # db using SQLAlchemy
class Data(db.Model):
x = db.Column(db.Float(), required=True)
y = db.Column(db.Float(), required=True)
d = db.Column(db.Float())
如何序列化这个对象,以便x
嵌套y
到coordinates
中,同时在后台(模型)中保持平面数据结构?输出应如下所示:
{
"coordinates": {
"x": 10.56
"y": 1
},
"d": 42.0
}
问题之所以出现,是因为我使用带有选项的Data
架构。many=True
初始化大致是:
schema_data = MomentData()
schema_datas = MomentData(many=True)
解决方案候选者
所以这是我迄今为止尝试过的,但它们似乎都没有奏效。
创建第二个架构
添加第二个模式并Data
从之前修改模式会产生:
class CoordinatesSchema(Schema):
x = fields.Float(required=True)
y = fields.Float(required=True)
class DataSchema(Schema):
coordinates = fields.Nested(coordinatesSchema, required=True)
d = fields.Float()
有了它会引发必须遍历每个Data
项目并手动添加Coordinates
架构的问题。我的数据来自返回Data
对象列表的 SQLAlchemy 查询,因此我可以使用schema_datas
.
使用fields.Dict
由于 Marshmallowsfields
模块提供了字典,所以我也尝试过。
def DataSchema(Schema):
coordinates = fields.Dict(keys=fields.String(),
value=fields.Float(),
required=True,
default={
"x": Data.x,
"y": Data.y
})
d = fields.Float()
似乎也不起作用,因为 MarshmallowData.x
在Data.y
使用schema_datas.dump()
.
使用自嵌套
最合乎逻辑的解决方案是自嵌套。但是(根据我阅读文档的理解)自嵌套仅指在对象中嵌套一个或多个其他实例。我想嵌套同一个实例。
class DataSchema(Schema):
x = fields.Float(required=True, load_only=True)
y = fields.Float(required=True, load_only=True)
coordinates = fields.Nested(
lambda: DataSchema(only=('x', 'y')),
dump_only=True)
但不幸的是,这也没有奏效。
使用装饰器@pre_dump
受Marshmallow 的 Github 页面上这个问题的启发,我尝试使用@pre_dump
装饰器来达到预期的结果,但又失败了。
class CoordinatesSchema(Schema):
x = fields.Float(required=True)
y = fields.Float(required=True)
class DataSchema(Schema):
coordinates = fields.Nested(coordinatesSchema, required=True)
d = fields.Float()
@pre_dump
def group_coordinates(self, data, many):
return {
"coordinates": {
"x": data.x,
"y": data.y
},
"d": data.d
}
但我无法弄清楚如何正确地做到这一点......
所以我的问题是,我做错了什么,我该如何解决这个问题?