【问题标题】:Flask Marshmallow serialize many to many relation with extra fieldFlask Marshmallow 用额外字段序列化多对多关系
【发布时间】:2020-02-11 23:12:46
【问题描述】:

我在带有序列化模型对象的 Flask 应用程序中遇到问题,该对象与存储在关联表中的额外字段具有多对多关系。我想要一个看起来像这样的序列化数据:

{
    "id": "123",
    "name": "name",
    "mobile": "phone number",
    "interest": [1, 2, 3]
    "_embedded": {
        "interest": [
            {
                "id": 1,
                "name": "ECONOMIC",
                "active": true,
            },
            {
                "id": 2,
                "name": "POETRY",
                "active": true,
            },
            {
                "id": 3,
                "name": "SPORT",
                "active": false,
            },
        ]
    }
}

现在我设法准备了一个必要的模型如下:

class OwnerInterests(db.Model):
    owner_id = db.Column(db.Integer, db.ForeignKey('owners.id'), primary_key=True)
    interest_id = db.Column(db.Integer, db.ForeignKey('interests.id'), primary_key=True)
    active = db.Column(db.Boolean)
    interest = db.relationship('Interests', back_populates='owners')
    owner = db.relationship('Owners', back_populates='interests')


class Owners(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    mobile = db.Column(db.String)
    interests = db.relationship('OwnersInterests', back_populates='owner')


class Interests(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    owners = db.relationship('OwnersInterests', back_populates='interest')

但现在我想知道方法,如何使用棉花糖模式准备 sqlalchemy 查询。有什么想法吗?

编辑:

我当前的棉花糖架构如下:

class InterestSchema(ma.ModelSchema):
    class Meta:
        model = Interests
        exclude = ('owners',)


class OwnerSchema(ma.ModelSchema):
    interests = ma.Nested(InterestSchema, many=True)

    class Meta:
        model = Owners

【问题讨论】:

  • 你能举一个你想要的例子吗?数据库和序列化是什么关系?
  • @TommyHerbert 模型之间的关系是多对多的,包括关联表(参见 sn-p with models)。我还在编辑中添加了棉花糖模式。
  • 听起来好像您正在尝试使用 SQLAlchemy 来查询文件系统而不是数据库。那正确吗?如果是这样,你为什么要这么做?
  • 在我的情况下,数据是数据库中的事实,我想在我的问题开始时根据示例 json 准备适当的烧瓶响应。
  • 哦,我想我现在明白了。那么第一步是从数据库中检索对象,第二步是使用 Marshmallow 从对象中生成 JSON 数据?

标签: python flask serialization sqlalchemy marshmallow


【解决方案1】:

此架构为您提供与您的规范非常相似的内容:

from marshmallow import Schema, fields


class InterestSchema(Schema):
    class Meta:
        fields = ('id', 'name')
        ordered = True


class OwnerInterestSchema(Schema):
    interest = fields.Nested(InterestSchema)

    class Meta:
        fields = ('id', 'interest', 'active')
        ordered = True


class OwnerSchema(Schema):
    interests = fields.Nested(OwnerInterestSchema, many=True)

    class Meta:
        fields = ('id', 'name', 'mobile', 'interests')
        ordered = True

然后您可以像这样序列化您的数据(请注意,我的模型与您的模型名称不完全相同):

>>> from app.serialisation import OwnerSchema
>>> from app.models import Owner
>>> data = OwnerSchema().dump(Owner.query.get(1))
>>> from marshmallow import pprint
>>> pprint(data)
{"id": 1, "name": "John", "mobile": "07123456789", "interests": [{"interest": {"id": 1, "name": "Economics"}, "active": true}, {"interest": {"id": 2, "name": "Poetry"}, "active": true}, {"interest": {"id": 3, "name": "Sport"}, "active": false}]}

让我缩进那个输出,这样你就可以看到发生了什么:

{
  "id": 1,
  "name": "John",
  "mobile": "07123456789",
  "interests": [
    {
      "interest": {
        "id": 1,
        "name": "Economics"
      },
      "active": true
    },
    {
      "interest": {
        "id": 2,
        "name": "Poetry"
      },
      "active": true
    },
    {
      "interest": {
        "id": 3,
        "name": "Sport"
      },
      "active": false
    }
  ]
}

如果需要,您可以调整它以使用模型加排除范式。如果您真的想要 JSON 中的 "_embedded" 字段,您可能需要一个自定义字段,如 here 所述。

您也可以使用自定义字段来平息您的兴趣,并将"active" 字段与"id""name" 放在同一级别,但我认为这会产生误导。

【讨论】:

  • 您关于创建关联模式的想法很好。我使用 post_dump 装饰器自定义将兴趣部分包装到 _embedded 键中。官方棉花糖示例 - marshmallow.readthedocs.io/en/stable/…
  • 这个例子对我来说非常有价值,因为我意识到通过单个模型的查询,您还可以从相关表中提取所有数据,以避免 SQLAlchemy 在查询中返回的元组
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多