最近抽空造了一个数据校验的轮子 Python -validator

2018-07-30 14:32:28 +08:00
 lxy42

最近抽空造了一个数据校验的轮子 python-validator

在开发 web 应用时,经常需要校验前端传入的数据。如果使用 Django,那么可以使用自带的 forms 进行数据校验。

python-validator 的灵感也是来源于 Django 的 forms (类似 ORM 的方式定义数据结构),不过 python-validator 更加纯粹,只是数据校验,另外也支持使用 dict 定义数据结构,相比于使用类更加方便。

欢迎大家提建议。觉得不错麻烦给个 star 吧!

下面是简单的介绍:

python-validator 是一个类似于 Django ORM 的数据校验库,适用与任何需要进行数据校验的应用,比较常见的是 Web 后端校验前端的输入数据。

特性

依赖

安装

pip install python-validator

快速入门

假设现在正在开发一个上传用户信息的接口 POST /api/user/,用户信息如下:

原始的、枯燥无味的、重复性劳动的数据校验代码可能是下面这样:

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'}

错误信息解释:

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
3724 次点击
所在节点    Python
14 条回复
onlywinnie
2018-07-30 15:08:20 +08:00
先 start 为敬🌚
Trim21
2018-07-30 15:16:00 +08:00
好东西…
能否允许尝试把“ 24 ”被转换为 24 之后再进行校验?
放在 query string 里面的整数一般取出来还是字符串类型…
Trim21
2018-07-30 15:16:32 +08:00
@Trim21 把“ 24 ”转换为 24
Trim21
2018-07-30 15:19:58 +08:00
@Trim21 原来文档里有…无视我😂
lxy42
2018-07-30 15:30:19 +08:00
@Trim21 #2 我当初考虑到了这个情况,将 strict 设为 False 就会尝试进行类型转换了。

同理,StringField 也可以允许非字符串类型的数据,只要可以转换成字符串。
omph
2018-07-30 16:00:52 +08:00
star 了,挺有用的工具
E1n
2018-07-30 16:11:29 +08:00
GJ!
d18
2018-07-30 16:21:45 +08:00
marshmallow ?
lxy42
2018-07-30 16:42:27 +08:00
@d18 #8 刚看了一下这个库,是有点类似。
ebingtel
2018-07-31 09:09:36 +08:00
看着比 wtforms 舒服
lxy42
2018-07-31 10:57:04 +08:00
@ebingtel #10 如果在使用过程中遇到问题欢迎提交 issue。
conn4575
2018-08-02 08:59:17 +08:00
挺好的,不过 django-restful 里面有个类似的,可以参考一下,我之前用过 schema 来做验证,不过对于嵌套的 json 比较捉急,不知道你这个可以吗?
lxy42
2018-08-02 09:15:08 +08:00
@conn4575 #12 你说的是 Django-restfulframework 的 serializer 吗? serializer 其实和 Django 自带的 forms 表单验证是类似的,多了反序列化功能。

schema 我也看了一下,感觉描述数据约束的方式不够优雅和直观。

python-validator 支持嵌套的。使用 DictField 就行了,文档在这里 https://ausaki.github.io/python-validator/fields/#dictfield。
gjquoiai
2018-08-03 18:25:22 +08:00
_(:з)∠)_ 用惯了 jsonschema

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/475344

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX