Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python marshmallow`validate_schema`拒绝带有`pass_many=True'的未知字段`_Python_Marshmallow - Fatal编程技术网

Python marshmallow`validate_schema`拒绝带有`pass_many=True'的未知字段`

Python marshmallow`validate_schema`拒绝带有`pass_many=True'的未知字段`,python,marshmallow,Python,Marshmallow,当模式被传递给一个要验证的对象列表时,我很难理解如何处理未知字段。我到目前为止: class MySchema(Schema): # fields ... @marshmallow_decorators.validates_schema(pass_original=True) def check_unknown_fields(self, data, original_data): if isinstance(original_data, list):

模式
被传递给一个要验证的对象列表时,我很难理解如何处理未知字段。我到目前为止:

class MySchema(Schema):
    # fields ...

    @marshmallow_decorators.validates_schema(pass_original=True)
    def check_unknown_fields(self, data, original_data):
        if isinstance(original_data, list):
            for dct in original_data:
                self._assert_no_unknown_field(dct)
        else:
            self._assert_no_unknown_field(original_data)

    def _assert_no_unknown_field(self, dct):
        unknown = set(dct.keys()) - set(self.fields)
        if unknown:
            raise MarshmallowValidationError('Unknown field', unknown)
但这显然不起作用,因为每次都会对列表中的所有项运行验证器。因此,将捕获第一个错误,并返回所有项目:

items = [
    {'a': 1, 'b': 2, 'unknown1': 3},
    {'a': 4, 'b': 5, 'unknown2': 6},
]
errors = MySchema(many=True).validate(items)
# {0: {'unknown1': ['Unknown field']}, 1: {'unknown1': ['Unknown field']}}
我试图想办法只从
data
参数对应的
original_data
中获取单个项目,并只验证其中一个,但我真的无法做到这一点,因为项目没有id,或者没有可以使其可搜索的字段


我错过什么了吗?有解决办法吗?

这是我想出的一个解决办法。。。我希望它更简单,但这里是:

from marshmallow import Schema, ValidationError as MarshmallowValidationError, fields

UNKNOWN_MESSAGE = 'unknown field'


class _RejectUnknownMixin(object):

    def _collect_unknown_fields_errors(self, schema, data):
        """
        Checks `data` against `schema` and returns a dictionary `{<field>: <error>}`
        if unknown fields detected, or `{0: {<field>: <error>}, ... N: <field>: <error>}`
        if `data` is a list.
        """
        if isinstance(data, list):
            validation_errors = {}
            for i, datum in enumerate(data):
                datum_validation_errors = self._collect_unknown_fields_errors(schema, datum)
                if datum_validation_errors:
                    validation_errors[i] = datum_validation_errors
            return validation_errors

        else:
            unknown = set(data.keys()) - set(schema.fields)
            return {name: [UNKNOWN_MESSAGE] for name in unknown}


class NestedRejectUnknown(fields.Nested, _RejectUnknownMixin):
    """
    Nested field that returns validation errors if unknown fields are detected.
    """

    def _deserialize(self, value, attr, data):
        validation_errors = {}
        try:
            result = super(NestedRejectUnknown, self)._deserialize(value, attr, data)
        except MarshmallowValidationError as err:
            validation_errors = err.normalized_messages()

        # Merge with unknown field errors
        validation_errors = _merge_dicts(
            self._collect_unknown_fields_errors(self.schema, value), validation_errors)
        if validation_errors:
            raise MarshmallowValidationError(validation_errors)

        return result


class SchemaRejectUnknown(Schema, _RejectUnknownMixin):
    """
    Schema that return validation errors if unknown fields are detected
    """

    def validate(self, data, **kwargs):
        validation_errors = super(SchemaRejectUnknown, self).validate(data, **kwargs)
        return _merge_dicts(
            self._collect_unknown_fields_errors(self, data), validation_errors)


def _merge_dicts(a, b, path=None):
    """
    Ref : https://stackoverflow.com/questions/7204805/dictionaries-of-dictionaries-merge
    merges b into a
    """
    if path is None:
        path = []
    for key in b:
        if key in a:
            if isinstance(a[key], dict) and isinstance(b[key], dict):
                _merge_dicts(a[key], b[key], path + [str(key)])
            elif a[key] == b[key]:
                # same leaf value
                pass
            else:
                raise Exception('Conflict at %s' % '.'.join(path + [str(key)]))
        else:
            a[key] = b[key]
    return a
从marshmallow导入架构,ValidationError作为MarshmallowValidationError,字段
未知消息='未知字段'
类_RejectUnknownMixin(对象):
定义\u收集\u未知\u字段\u错误(自身、架构、数据):
"""
根据“schema”检查“data”,并返回字典“{:}”`
如果检测到未知字段,或`{0:{:},…N:}`
如果'data'是一个列表。
"""
如果存在(数据、列表):
验证_错误={}
对于i,枚举中的数据(数据):
数据\验证\错误=自身。\收集\未知\字段\错误(模式、数据)
如果数据\验证\错误:
验证错误[i]=基准验证错误
返回验证错误
其他:
unknown=set(data.keys())-set(schema.fields)
为未知}中的名称返回{name:[UNKNOWN_MESSAGE]
类NestedRejectUnknown(fields.Nested,_RejectUnknownMixin):
"""
如果检测到未知字段,则返回验证错误的嵌套字段。
"""
def_反序列化(self、value、attr、data):
验证_错误={}
尝试:
结果=超级(NestedRejectUnknown,self)。\u反序列化(值、属性、数据)
除MarshmallowValidationError作为错误外:
验证\u错误=err.normalized\u消息()
#合并未知字段错误
验证\u错误=\u合并\u指令(
self.\u收集\u未知\u字段\u错误(self.schema、值)、验证\u错误)
如果验证错误:
引发MarshmallowValidationError(验证错误)
返回结果
类SchemaRejectUnknown(Schema,\u RejectUnknownMixin):
"""
如果检测到未知字段,则返回验证错误的架构
"""
def验证(自身、数据、**kwargs):
验证_errors=super(SchemaRejectUnknown,self)。验证(数据,**kwargs)
返回\u合并\u命令(
self.\u收集\u未知\u字段\u错误(self、数据)、验证\u错误)
定义合并命令(a,b,路径=无):
"""
裁判:https://stackoverflow.com/questions/7204805/dictionaries-of-dictionaries-merge
将b合并为a
"""
如果路径为“无”:
路径=[]
对于b键:
如果输入a:
如果isinstance(a[键],dict)和isinstance(b[键],dict):
_合并指令(a[键]、b[键]、路径+[键])
如果a[键]==b[键]:
#相同叶值
通过
其他:
引发异常(“%s”%”处发生冲突。加入(路径+[str(键)])
其他:
a[键]=b[键]
归还

这是我想出的一个解决办法。。。我希望它更简单,但这里是:

from marshmallow import Schema, ValidationError as MarshmallowValidationError, fields

UNKNOWN_MESSAGE = 'unknown field'


class _RejectUnknownMixin(object):

    def _collect_unknown_fields_errors(self, schema, data):
        """
        Checks `data` against `schema` and returns a dictionary `{<field>: <error>}`
        if unknown fields detected, or `{0: {<field>: <error>}, ... N: <field>: <error>}`
        if `data` is a list.
        """
        if isinstance(data, list):
            validation_errors = {}
            for i, datum in enumerate(data):
                datum_validation_errors = self._collect_unknown_fields_errors(schema, datum)
                if datum_validation_errors:
                    validation_errors[i] = datum_validation_errors
            return validation_errors

        else:
            unknown = set(data.keys()) - set(schema.fields)
            return {name: [UNKNOWN_MESSAGE] for name in unknown}


class NestedRejectUnknown(fields.Nested, _RejectUnknownMixin):
    """
    Nested field that returns validation errors if unknown fields are detected.
    """

    def _deserialize(self, value, attr, data):
        validation_errors = {}
        try:
            result = super(NestedRejectUnknown, self)._deserialize(value, attr, data)
        except MarshmallowValidationError as err:
            validation_errors = err.normalized_messages()

        # Merge with unknown field errors
        validation_errors = _merge_dicts(
            self._collect_unknown_fields_errors(self.schema, value), validation_errors)
        if validation_errors:
            raise MarshmallowValidationError(validation_errors)

        return result


class SchemaRejectUnknown(Schema, _RejectUnknownMixin):
    """
    Schema that return validation errors if unknown fields are detected
    """

    def validate(self, data, **kwargs):
        validation_errors = super(SchemaRejectUnknown, self).validate(data, **kwargs)
        return _merge_dicts(
            self._collect_unknown_fields_errors(self, data), validation_errors)


def _merge_dicts(a, b, path=None):
    """
    Ref : https://stackoverflow.com/questions/7204805/dictionaries-of-dictionaries-merge
    merges b into a
    """
    if path is None:
        path = []
    for key in b:
        if key in a:
            if isinstance(a[key], dict) and isinstance(b[key], dict):
                _merge_dicts(a[key], b[key], path + [str(key)])
            elif a[key] == b[key]:
                # same leaf value
                pass
            else:
                raise Exception('Conflict at %s' % '.'.join(path + [str(key)]))
        else:
            a[key] = b[key]
    return a
从marshmallow导入架构,ValidationError作为MarshmallowValidationError,字段
未知消息='未知字段'
类_RejectUnknownMixin(对象):
定义\u收集\u未知\u字段\u错误(自身、架构、数据):
"""
根据“schema”检查“data”,并返回字典“{:}”`
如果检测到未知字段,或`{0:{:},…N:}`
如果'data'是一个列表。
"""
如果存在(数据、列表):
验证_错误={}
对于i,枚举中的数据(数据):
数据\验证\错误=自身。\收集\未知\字段\错误(模式、数据)
如果数据\验证\错误:
验证错误[i]=基准验证错误
返回验证错误
其他:
unknown=set(data.keys())-set(schema.fields)
为未知}中的名称返回{name:[UNKNOWN_MESSAGE]
类NestedRejectUnknown(fields.Nested,_RejectUnknownMixin):
"""
如果检测到未知字段,则返回验证错误的嵌套字段。
"""
def_反序列化(self、value、attr、data):
验证_错误={}
尝试:
结果=超级(NestedRejectUnknown,self)。\u反序列化(值、属性、数据)
除MarshmallowValidationError作为错误外:
验证\u错误=err.normalized\u消息()
#合并未知字段错误
验证\u错误=\u合并\u指令(
self.\u收集\u未知\u字段\u错误(self.schema、值)、验证\u错误)
如果验证错误:
引发MarshmallowValidationError(验证错误)
返回结果
类SchemaRejectUnknown(Schema,\u RejectUnknownMixin):
"""
如果检测到未知字段,则返回验证错误的架构
"""
def验证(自身、数据、**kwargs):
验证_errors=super(SchemaRejectUnknown,self)。验证(数据,**kwargs)
返回\u合并\u命令(
self.\u收集\u未知\u字段\u错误(self、数据)、验证\u错误)
定义合并命令(a,b,路径=无):
"""
裁判:https://stackoverflow.com/questions/7204805/dictionaries-of-dictionaries-merge
将b合并为a
"""
如果路径为“无”:
路径=[]
对于b键:
如果输入a:
如果isinstance(a[键],dict)和isinstance(b[键],dict):
_合并指令(a[键]、b[键]、路径+[键])
如果a[键]==b[键]:
#相同叶值