如何在棉花糖中人为嵌套架构?



在棉花糖中,有没有办法将当前对象传递给Nested字段以生成人工嵌套的序列化?例如,考虑我正在序列化的这个对象:

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

我想为此生成如下所示的 JSON:

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

本质上,这将是ExampleSchema内部的嵌套AddressSchema,如下所示:

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

。但这并不完全符合我的意愿。我可以使用自定义函数,但如果可能的话,我想使用内置方法。

我设法找到了一个解决方案,允许我保留内省并仅使用内置字段; 不过,这有点奇怪。我修改了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)

您可以按如下方式定义地址字段

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

归功于这篇文章:嵌套在 Python 和棉花糖中,其中包含数据库中不存在的字段

我无法得到被接受的答案。我想将一些成员嵌套为帐户中的"首选项"架构。

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())

我使用 marshmallow 的pre_dump装饰器调用了一个函数,该函数将首选项对象设置到模型上:

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

现在的响应将是:

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

相关内容

  • 没有找到相关文章

最新更新