最近抽空造了一个数据校验的轮子 python-validator。
在开发 web 应用时,经常需要校验前端传入的数据。如果使用 Django,那么可以使用自带的 forms 进行数据校验。
python-validator 的灵感也是来源于 Django 的 forms (类似 ORM 的方式定义数据结构),不过 python-validator 更加纯粹,只是数据校验,另外也支持使用 dict 定义数据结构,相比于使用类更加方便。
欢迎大家提建议。觉得不错麻烦给个 star 吧!
下面是简单的介绍:
python-validator 是一个类似于 Django ORM 的数据校验库,适用与任何需要进行数据校验的应用,比较常见的是 Web 后端校验前端的输入数据。
支持 python2 和 python3。
使用类描述数据结构,数据字段一目了然。另外也支持使用字典定义数据结构。
可以自动生成用于测试的 mocking data。
可以打印出清晰的数据结构。
易于扩展。
six
IPy
pytz[可选,DatetimeField
的 tzinfo
参数需要一个 tzinfo
对象]
pip install python-validator
假设现在正在开发一个上传用户信息的接口 POST /api/user/
,用户信息如下:
name
string,必选。
age
integer,可选,默认 20。
sex
string, 'f'表示女, 'm'表示男。可选, 默认 None。
原始的、枯燥无味的、重复性劳动的数据校验代码可能是下面这样:
def user(request):
# data = json.loads(request.body)
data = {
'age': '24f',
'sex': 'f'
}
name = data.get('name')
age = data.get('age', 20)
sex = dage.get('sex')
if name is None or len(name) == 0:
return Response('必须提供 name', status=400)
try:
age = int(age)
except ValueError as e:
return Response('age 格式错误', status=400)
if sex is not None and sex not in ('f', 'm'):
return Response('sex 格式错误', status=400)
user_info = {
'name': name,
'age': age,
'sex': sex,
}
...
上面这段代码总的来说有几个问题:
枯燥无味和重复性代码,不断的取出数据,检查字段是否缺失,类型是否合法等等。
从数据校验的代码无法轻易看出用户信息的数据结构,即字段是什么类型的,是否可选,默认值是什么。
使用 python-validator 校验数据
首先定义一个 UserInfoValidator 类
# validators.py
from validator import Validator, StringField, IntegerField, EnumField
class UserInfoValidator(Validator):
name = StringField(max_length=50, required=True)
age = IntegerField(min_value=1, max_value=120, default=20)
sex = EnumField(choices=['f', 'm'])
接下来使用 UserInfoValidator
进行数据校验,
from .validators import UserInfoValidator
def user(request):
# data = json.loads(request.body)
data = {
'age': '24',
'sex': 'f'
}
v = UserInfoValidator(data)
if not v.is_valid():
return Response({'msg': v.str_errors, 'code': 400}, status=400)
user_info = v.validated_data
...
v.str_errors
是一个字段名 - 错误信息的 dict,例如:
{'age': 'got a wrong type: str, expect integer', 'name': 'Field is required'}
错误信息解释:
age
等于 "24",不是合法的 int
类型。
name
是必须提供的,且没有指定默认值。
v.validated_data 是校验后合法的数据,例如:
{'age': 24, 'name': u'Michael', 'sex': 'f'}
下面是一些错误数据的例子:
data: {'age': 24, 'name': 'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc', 'sex': 'f'}
is_valid: False
errors: {'name': 'string is too long, max-lenght is 50'}
validated_data: None
data: {'age': 24, 'name': 'Michael', 'sex': 'c'}
is_valid: False
errors: {'sex': "'c' not in the choices"}
validated_data: None
1
onlywinnie 2018-07-30 15:08:20 +08:00
先 start 为敬🌚
|
2
Trim21 2018-07-30 15:16:00 +08:00 via Android
好东西…
能否允许尝试把“ 24 ”被转换为 24 之后再进行校验? 放在 query string 里面的整数一般取出来还是字符串类型… |
5
lxy42 OP |
6
omph 2018-07-30 16:00:52 +08:00
star 了,挺有用的工具
|
7
E1n 2018-07-30 16:11:29 +08:00
GJ!
|
8
d18 2018-07-30 16:21:45 +08:00 1
marshmallow ?
|
10
ebingtel 2018-07-31 09:09:36 +08:00
看着比 wtforms 舒服
|
12
conn4575 2018-08-02 08:59:17 +08:00 via Android
挺好的,不过 django-restful 里面有个类似的,可以参考一下,我之前用过 schema 来做验证,不过对于嵌套的 json 比较捉急,不知道你这个可以吗?
|
13
lxy42 OP @conn4575 #12 你说的是 Django-restfulframework 的 serializer 吗? serializer 其实和 Django 自带的 forms 表单验证是类似的,多了反序列化功能。
schema 我也看了一下,感觉描述数据约束的方式不够优雅和直观。 python-validator 支持嵌套的。使用 DictField 就行了,文档在这里 https://ausaki.github.io/python-validator/fields/#dictfield。 |
14
gjquoiai 2018-08-03 18:25:22 +08:00
_(:з)∠)_ 用惯了 jsonschema
|