Skip to content
kk edited this page Jun 1, 2019 · 3 revisions

Schema 和 Model

from validr import T, modelclass

schema1 = T.dict(
    id=T.int.desc('The unique identifier for a product'),
    name=T.str.desc('Name of the product'),
    price=T.float.exmin(0),
    tags=T.list(
        T.str.minlen(1)
    ).unique
)

schema2 = T({
    "$self": "dict",
    "id": "int.desc('The unique identifier for a product')",
    "name": "str.desc('Name of the product')",
    "price": "float.exmin(0)",
    "tags": [
        "list.unique",
        "str.minlen(1)"
    ]
})

@modelclass
class Product:
    id=T.int.desc('The unique identifier for a product')
    name=T.str.desc('Name of the product')
    price=T.float.exmin(0)
    tags=T.list(
        T.str.minlen(1)
    ).unique

# 它们是等价的
assert schema1 == schema2 == Product
# 转换成JSON字符串内容是一样的
assert str(schema1) == str(schema2) == str(Product.__schema__)
# 可Hash,可作为字典的Key
assert hash(schema1) == hash(schema2) == hash(Product.__schema__)

Compiler

Schema 需要编译后才能校验数据,这么做有两个原因:

  1. 编译相对来说比较耗时的,并且编译只需要执行一次,这样可以提高性能
  2. 编译过程中可以拓展 Schema,比如自定义校验器
from validr import Compiler

compiler = Compiler()
validate = compiler.compile(schema)

校验数据

>>> from validr import T, Compiler, Invalid
>>> f = Compiler().compile(T.int.min(0).max(9))
>>> f("3")
3
>>> f(-1)
...
validr._exception.Invalid: value must >= 0, value=-1
>>> f("abc")
...
validr._exception.Invalid: invalid int, value=abc

转换成字符串或对象:

>>> Compiler().compile(T.date)('2019-01-01')
'2019-01-01'
>>> Compiler().compile(T.date.object)('2019-01-01')
datetime.date(2019, 1, 1)
>>>

处理异常

异常类型

ValidrError
  - Invalid
      - ModelInvalid
  - SchemaError

处理校验错误

f = Compiler().compile(
    T.dict(
        numbers=T.list(T.int)
    )
)
try:
    f({"numbers":[1,'x']})
except Invalid as ex:
    print(ex.message)
    print(ex.position)
    print(ex.field)
    print(ex.value)
    print(str(ex))
>>>
invalid int
numbers[1]
numbers
x
numbers[1]: invalid int, value=x
>>>

替换异常值,不抛出异常:

>>> Compiler().compile(T.int.invalid_to(0))('x')
0
>>> Compiler().compile(T.int.default(0).invalid_to_default)('x')
0
>>> Compiler().compile(T.int.optional.invalid_to_default)('x')
None

记录错误位置

mark_indexmark_key 是用来向 ValidrError 或者它的子类对象 (例如:Invalid 和 SchemaError)中添加出错位置信息。

from validr import mark_index, mark_key, ValidrError
try:
    with mark_index(0):
        with mark_key('key'):
            with mark_index(-1):  # `-1` 表示位置不确定
                raise ValidrError('message')
except ValidrError as ex:
    print(ex.position)  # [0].key[], 其中的 `[]` 对应于 mark_index(-1)