前言

  cerberus 翻译为地狱犬,是地狱的看门狗,比喻做数据的校验者。
  这个库是专门用来校验做数据校验。
  可以通过定义一个 schema 文件来快速校验数据是否复合 schema。

Github 地址
官方说明文档

cerberus 介绍

cerberus 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from cerberus import Validator

schema = {
"name": {"type": "string"},
"member": {
"type": "dict",
"require_all": True,
"schema": {"address": {"type": "string"}},
},
}
v = Validator(schema)
document = {"name": "john doe", "member": {}}
result = v.validate(document)
print(result) # 打印 False
print(v.errors) # 打印 {'member': [{'address': ['required field']}]}

  主要用法就是定义一个规范。
  cerberus 会根据这个规范对数据进行校验。
  这其中的规则既可以根据官方文档添加,也可以继承 Validator 实现自定义的规则。

cerberus 嵌套检查

1
2
3
4
5
6
7
8
from cerberus import schema_registry

schema_registry.add("non-system user", {"uid": {"min": 1000, "max": 0xFFFF}})
schema = {
"sender": {"schema": "non-system user", "allow_unknown": True},
"receiver": {"schema": "non-system user", "allow_unknown": True},
}

  导入 schema_registry 添加到里面的 schema 可以被别的地方复用。
  别的 schema 只要输入相应的字符串就可以复用 schema
  或者也可以通过接入字典变量的方式来复用 schema

cerberus 自定义检查功能

  扩展检查规则可以通过继承 Validator 来实现,非常简单方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from cerberus import Validator

class MyValidator(Validator):
def _validate_is_odd(self, constraint, field, value):
""" Test the oddity of a value.

The rule's arguments are validated against this schema:
{'type': 'boolean'}
"""
if constraint is True and not bool(value & 1):
self._error(field, "Must be an odd number")

schema = {'amount': {'is odd': True, 'type': 'integer'}}
v = MyValidator(schema)
v.validate({'amount': 10}) # 打印 False

结合 marshmallow 使用

  使用 cerberus 的 schema 可以让校验规则统一到一个地方进行配置。
  配置更加清晰,查找也比较方便。
  相较于使用 attrs 或者 marshmallow 提供校验功能。
  cerberus 可以更加清晰地配置和修改。

  我上一篇文章介绍了使用 marshmallow 可以很方便地对数据进行序列化。
  同时它也可以对每一个 field 编写函数进行数据校验,但是如果使用 嵌套 Schema 的话
  这些校验方法东一块西一块,配置和修改都非常繁琐。
  这个使用可以结合 marshmallowvalidates_schema 装饰器通过函数调用 cerberus 进行数据校验。 marshmallow 文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from marshmallow import Schema, fields, validates_schema, ValidationError
from cerberus import Validator

schema = {
"field_a": {
"required": True,
"type": "integer",
"min": 0,
"max": 5,
}
}
validator = Validator(schema)


class MySchema(Schema):
field_a = fields.Int(required=True)
field_b = fields.Int(required=True)

@validates_schema(pass_original=True)
def validate_schema(self, data, original_data):
if not validator.validate(original_data):
raise ValidationError(validator.errors)


schema = MySchema()
document = {
"field_a": -1,
"field_b": -1,
}
res, err = schema.load(document)
print(err) # 打印 {'_schema': [{'field_a': ['min value is 0'], 'field_b': ['unknown field']}]}

  这样就可以实现反序列化数据的同时进行数据校验。

总结

  cerberus 其实也可以做数据的 coerce ,实现一定程度的序列化功能。
  不过如果需要嵌套的话,还是用 marshmallow 进行处理比较方便。
  而且 marshmallow 嵌套调用也可以配合着 cerberus 顺便进行数据校验。