[英]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.