使用棉花糖指定一个或多个字段

Specify a one or many field using marshmallow

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

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

我能否拥有一个既允许单个项目又允许多个项目的架构?

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

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']]