我在Cerberus中有验证规则,需要自定义验证器。访问self.document
中的字段时,即使使用"required"
标志,我也必须验证那些字段是否存在。我正在寻找一种"required"
标志来为我处理此问题的方法。
例如,假设我有一个名为data
的字典,该字典包含数组a
和b
,并规定a
和b
都是必需的, len(a) == len(b)
。
# Schema
schema = {'data':
{'type': 'dict',
'schema': {'a': {'type': 'list',
'required': True,
'length_b': True},
'b': {'type': 'list',
'required': True}}}}
# Validator
class myValidator(cerberus.Validator):
def _validate_length_b(self, length_b, field, value):
"""Validates a field has the same length has b"""
if length_b:
b = self.document.get('b')
if not len(b) == len(value):
self._error(field, 'is not equal to length of b array')
如果存在a
和b
,则此方法很好:
good = {'data': {'a': [1, 2, 3],
'b': [1, 2, 3]}}
v = myValidator()
v.validate(good, schema)
# True
bad = {'data': {'a': [1, 2, 3],
'b': [1, 3]}}
v.validate(bad, schema)
# False
v.errors
# {'data': [{'a': ['is not equal to length of b array']}]}
但是,如果缺少b
,它将从TypeError
返回len()
。
very_bad = {'data': {'a': [1, 2, 3]}}
v.validate(very_bad, schema)
# TypeError: object of type 'NoneType' has no len()
如何获取validate
来返回False
(因为b
不存在)?我想要的输出如下:
v.validate(very_bad, schema)
# False
v.errors
# {'data': ['b': ['required field']]}
答案 0 :(得分:2)
以Validating that two params have same amount elements using Cerberus为灵感,可以做到:
schema = {'data':
{'type': 'dict',
'schema': {'a': {'type': 'list',
'required': True,
'match_length': 'b'},
'b': {'type': 'list',
'required': True}}}}
class MyValidator(cerberus.Validator):
def _validate_match_length(self, other, field, value):
if other not in self.document:
return False
elif len(value) != len(self.document[other]):
self._error(field,
"Length doesn't match field %s's length." % other)
然后:
v = MyValidator(schema)
good = {'data': {'a': [1, 2, 3],
'b': [1, 2, 3]}}
v.validate(good)
-> True
bad = {'data': {'a': [1, 2, 3],
'b': [1, 3]}}
v.validate(bad)
-> False
v.errors
-> {'data': [{'a': ["Length doesn't match field b's length."]}]}
very_bad = {'data': {'a': [1, 2, 3]}}
v.validate(very_bad)
-> False
v.errors
-> {'data': [{'b': ['required field']}]}