使用marshmallow指定一个或多个字段

时间:2017-07-13 18:43:30

标签: python-3.x schema marshmallow

我想指定一个架构字段wichi接受一个或多个资源。但是我似乎只能指定一种行为或另一种行为。

>>> class Resource(marshmallow.Schema):
...     data = marshmallow.fields.Dict()
... 
>>> class ContainerSchema(marshmallow.Schema):
...     resource = marshmallow.fields.Nested(ResourceSchema, many=True)
... 
>>> ContainerSchema().dump({'resource': [{'data': 'DATA'}]})
MarshalResult(data={'resource': [{'data': 'DATA'}]}, errors={})

在上面的例子中,必须定义一个列表。但是我不愿意:

>>> ContainerSchema().dump({'resource': {'data': 'DATA'}})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/lib64/python3.6/site-packages/marshmallow/schema.py", line 513, in dump
    **kwargs
  File "/lib64/python3.6/site-packages/marshmallow/marshalling.py", line 147, in serialize
    index=(index if index_errors else None)
  File "/lib64/python3.6/site-packages/marshmallow/marshalling.py", line 68, in call_and_store
    value = getter_func(data)
  File "/lib64/python3.6/site-packages/marshmallow/marshalling.py", line 141, in <lambda>
    getter = lambda d: field_obj.serialize(attr_name, d, accessor=accessor)
  File "/lib64/python3.6/site-packages/marshmallow/fields.py", line 252, in serialize
    return self._serialize(value, attr, obj)
  File "/lib64/python3.6/site-packages/marshmallow/fields.py", line 448, in _serialize
    schema._update_fields(obj=nested_obj, many=self.many)
  File "/lib64/python3.6/site-packages/marshmallow/schema.py", line 760, in _update_fields
    ret = self.__filter_fields(field_names, obj, many=many)
  File "/lib64/python3.6/site-packages/marshmallow/schema.py", line 810, in __filter_fields
    obj_prototype = obj[0]
KeyError: 0

我是否可以使用允许单个项目或多个项目的模式?

1 个答案:

答案 0 :(得分:1)

将参数作为列表给出 - 无论是一个还是多个 - 都是如此,架构知道如何在任何一种情况下处理它。要使模式处理不同格式的参数(例如不在列表中),您需要向模式添加预处理器,如下所示:

class ContainerSchema(marshmallow.Schema):
    resource = marshmallow.fields.Nested(ResourceSchema, many=True)
    @pre_dump
    def wrap_indata(self, indata):
        if type(indata['resource']) is dict:
            indata['resource'] = [indata['resource']]