简体   繁体   English

如何在 Marshmallow 中人为地嵌套模式?

[英]How can I artificially nest schemas in Marshmallow?

In Marshmallow, is there a way to pass the current object to a Nested field in order to produce artificially nested serializations?在 Marshmallow 中,有没有办法将当前的 object 传递给Nested字段以生成人为嵌套的序列化? For example, consider this object that I'm serializing:例如,考虑我正在序列化的这个 object:

example = Example(
    name="Foo",
    address="301 Elm Street",
    city="Kalamazoo",
    state="MI",
)

I want to produce JSON for this that looks like this:我想为此生成 JSON,如下所示:

{
    "name": "Foo",
    "address": {
            "street": "301 Elm Street",
            "city": "Kalamazoo",
            "state": "MI"
    }
}

Essentially, this would be a nested AddressSchema inside the ExampleSchema , something like this:本质上,这将是ExampleSchema中的嵌套AddressSchema ,如下所示:

class AddressSchema:
    street = fields.String(attribute="address")
    city = fields.String()
    state = fields.String()

class ExampleSchema:
    name = fields.String()
    address = fields.Nested(AddressSchema)

...but that doesn't quite do what I'd like. ...但这并不能完全满足我的要求。 I can use a custom function, but I'd like to use a built-in method if possible.我可以使用自定义 function,但如果可能,我想使用内置方法。

I managed to figure out a solution that allows me to preserve introspection and use only built-in fields;我设法找到了一个解决方案,允许我保留自省并仅使用内置字段; it's a little odd, though.不过,这有点奇怪。 I modified ExampleSchema to include a @pre_dump hook that adds a self-referential attribute, and pointed the field at that:我修改了ExampleSchema以包含一个@pre_dump钩子,该钩子添加了一个自引用属性,并将该字段指向:

class ExampleSchema:
    name = fields.String()
    address = fields.Nested(
        AddressSchema, attribute="_marshmallow_self_reference"
    )

    @pre_dump
    def add_self_reference(self, data):
        setattr(data, "_marshmallow_self_reference", data)

You can define the address field as follows您可以定义地址字段如下

address = fields.Function(lambda x: {'street': x.street, 'city': x.city, 'state': x.state})

Credit goes to this post: Nesting in Python and Marshmallow with a field that does not exist in the database感谢这篇文章: Nesting in Python and Marshmallow with a field that does not exist in the database

I couldn't get the accepted answer to work.我无法得到公认的工作答案。 I wanted to nest some members as as a "preferences" schema inside the account.我想将一些成员嵌套为帐户内的“首选项”架构。

class Color:
    id = Column(UUID)
    name = Column(Unicode(100))

class Account:
    id = Column(UUID())
    name = Column(Integer())
    age = Column(Integer())

    # These are the account's "preferences", which are stored
    # directly in the account model.
    color_ids = Column(ARRAY(UUID))
    colors = relationship("Color", primaryjoin... etc)
    opt_in = Column(Boolean())

I used marshmallow's pre_dump decorator to call a function that sets a preferences object onto the model:我使用 marshmallow 的pre_dump装饰器来调用 function,它将首选项 object 设置到 model:

class ColorSchema(SQLAlchemySchema):
    class Meta:
        model = models.Color
        fields = [ "id", "name" ]

# Subset of Account that I want returned as a nested entry
class PreferencesSchema(SQLAlchemySchema):
    class Meta:
        model = models.Account
        fields = [ "colors", "opt_in" ]

    colors = marshmallow.fields.List(marshmallow.fields.Nested(ColorSchema))

class AccountSchema(SQLAlchemySchema):
    class Meta:
        model = models.Account
        fields = [
            "id",
            "name",
            "age",
            "preferences" # Note: does not exist on model
        ]
    preferences = fields.Nested(PreferencesSchema)

    @pre_dump
    def set_preferences(self, data, **kwargs):
        preferences = {
            "colors": data.colors,
            "opt_in": data.opt_in,
        }
        setattr(data, "preferences", preferences)
        return data

Now the response would be:现在响应将是:

{
    "id": "uuid...",
    "name": "Joe",
    "age": 25,
    "preferences": {
        "colors": [
            { "id": "uuid...", "name": "blue" },
            { "id": "uuid...", "name": "red" },
        ],
        "opt_in": false
    }
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM