-
Notifications
You must be signed in to change notification settings - Fork 12
自定义校验器
guyskk edited this page Mar 29, 2020
·
3 revisions
validator()
装饰器用于创建自定义的校验器,并使它自动支持 default
, optional
, desc
, invalid_to
, invalid_to_default
, object
这几个通用参数。
你可以用 accept
和 output
参数控制校验器接受和输出的数据类型:
- accept (
str
|object
|(str,object)
):-
str
: 只接受字符串,将 None 和空字符串都视为 None -
object
: 只接受对象(非字符串) -
(str,object)
: (默认值) 接受字符串和对象,将 None 和空字符串都视为 None
-
- output (
str
|object
|(str,object)
):-
str
: (默认值) 只输出字符串,将 None 转换成空字符串 -
object
: 只输出对象(非字符串) -
(str, object)
: 输出字符串或对象,通过object
参数控制输出类型。为避免命名冲突,object
参数在校验器函数签名中会重命名为output_object
-
校验器的一般写法:
from validr import T, validator
@validator(accept=(str, object), output=(str, object))
def xxx_validator(compiler, items=None, output_object=False, some_param=None):
"""自定义校验器
Params:
compiler: 可以用它编译内部校验器
items: 可选,只能为标量类型,通过 T.validator(items) 形式的Schema指定
output_object: 控制是否输出对象, 只在 `output=(str, object)` 时有效
some_param: 其他参数
Returns:
校验函数
"""
def validate(value):
"""校验函数
Params:
value: 待校验的数据
Returns:
合法的值或处理后的值
Raises:
Invalid: 校验失败
"""
try:
# 数据校验和转换
except Exception:
# raise Invalid('invalid xxx')
if output_object:
# return python object
else:
# return string
return validate
# 使用自定义校验器
compiler = Compiler(validators={
# 名称: 校验器
'xxx': xxx_validator,
})
示例,时间间隔校验器:
from validr import T, validator, SchemaError, Invalid, Compiler
UNITS = {'s':1, 'm':60, 'h':60*60, 'd':24*60*60}
def to_seconds(t):
return int(t[:-1]) * UNITS[t[-1]]
@validator(accept=str, output=object)
def interval_validator(compiler, min='0s', max='365d'):
"""Time interval validator, convert value to seconds
Supported time units:
s: seconds, eg: 10s
m: minutes, eg: 10m
h: hours, eg: 1h
d: days, eg: 7d
"""
try:
min = to_seconds(min)
except (IndexError,KeyError,ValueError):
raise SchemaError('invalid min value') from None
try:
max = to_seconds(max)
except (IndexError,KeyError,ValueError):
raise SchemaError('invalid max value') from None
def validate(value):
try:
value = to_seconds(value)
except (IndexError,KeyError,ValueError):
raise Invalid("invalid interval") from None
if value < min:
raise Invalid("interval must >= {} seconds".format(min))
if value > max:
raise Invalid("interval must <= {} seconds".format(max))
return value
return validate
compiler = Compiler(validators={"interval": interval_validator})
f = compiler.compile(T.interval.max('8h'))
>>> f('15m')
900
>>> f('15x')
...
validr._exception.Invalid: invalid interval, value=15x
>>> f('10h')
...
validr._exception.Invalid: interval must <= 28800 seconds, value=10h
>>> f = compiler.compile(T.interval.default('5m'))
>>> f(None)
300
>>> compiler.compile(T.interval.max('12x'))
...
validr._exception.SchemaError: invalid max value, schema=interval.max('12x')
from validr import T, Compiler, create_re_validator
regex_time = r'([01]?\d|2[0-3]):[0-5]?\d:[0-5]?\d'
time_validator = create_re_validator("time", regex_time)
compiler = Compiler(validators={"time": time_validator})
f = compiler.compile(T.time.default("00:00:00"))
>>> f("12:00:00")
'12:00:00'
>>> f("12:00:123")
...
validr._exception.Invalid: invalid time, value=12:00:123
>>> f(None)
'00:00:00'
>>>