使用 Marshmallow 序列化对象时如何对字段进行分组?

问题描述 投票:0回答:1

问题

当使用 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

由于 Marshmallows

fields
模块提供了字典,我也尝试了。


def DataSchema(Schema):
  coordinates = fields.Dict(keys=fields.String(),
                            value=fields.Float(),
                            required=True,
                            default={
                                 "x": Data.x,
                                 "y": Data.y
                            })
  d = fields.Float()

似乎也不起作用,因为 Marshmallow 在使用

Data.x
时无法自动找到
Data.y
schema_datas.dump()

使用自我嵌套

最合乎逻辑的解决方案是自我筑巢。但是(根据我阅读文档的理解)自嵌套仅指在对象内嵌套一个或多个other实例。我想嵌套 same 实例。

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
    }

但我不知道如何正确地做到这一点...


所以我的问题是,我做错了什么以及如何解决这个问题?

python flask flask-sqlalchemy marshmallow flask-marshmallow
1个回答
0
投票

在与同样的问题作斗争之后,这是解决方案(与您建议的相去不远):

''' 类坐标模式(模式): x = fields.Float(必需=True) y = fields.Float(必需=True)

类DataSchema(模式): 坐标 = fields.Nested(coordinatesSchema, required=True) d = fields.Float()

@pre_dump def group_坐标(自身,数据,许多): 数据.坐标 = 数据 返回(数据) '''

© www.soinside.com 2019 - 2024. All rights reserved.