Python通过Schema实现数据验证方式


Posted in Python onNovember 12, 2020

Schema是什么?

不管我们做什么应用,只要和用户输入打交道,就有一个原则--永远不要相信用户的输入数据。意味着我们要对用户输入进行严格的验证,web开发时一般输入数据都以JSON形式发送到后端API,API要对输入数据做验证。一般我都是加很多判断,各种if,导致代码很丑陋,能不能有一种方式比较优雅的验证用户数据呢?Schema就派上用场了。

Schema非常简单,也就几百行的代码,最核心的类就一个:Schema。

1. 给Schema类传入类型(int、str、float等)

例如:

from schema import Schema

Schema(int).validate(10)
10
Schema(int).validate('10')
SchemaUnexpectedTypeError: '10' should be instance of 'int'

可见Schema会去验证validate方法传入的对象是不是所指定的类型,是则返回传入的数据,否则抛出一个SchemaError的异常(SchemaUnexpectedTypeError是SchemaError的子类)。

2. 给Schema类传入可调用的对象(函数、带__call__的类等)

例如:

Schema(lambda x: 0<x<10).validate(5)
5
Schema(lambda x: 0<x<10).validate(57)
SchemaError: <lambda>(57) should evaluate to True

可见Schema会把validate方法传入的值传入到对应的函数里面作为参数,如果函数返回值为True则返回输入数据,否则抛出异常。

3. 给Schema类传入带有validate方法的对象

Schema也内置了一些类(Use、And、Or等等),这些类的实例都带有validate方法,亦可作为Schema的参数传入,例如:

from schema import Schema, And

# And代表两个条件必须同时满足
Schema(And(str, lambda s: len(s) > 2)).validate('abcd')
'abcd'

4. 给Schema类传入容器对象(list、tuple、set等)

例如:

Schema([int, float]).validate([1, 2, 3, 4.0])
[1, 2, 3, 4.0]

相当于,对于[1, 2, 3, 4.0]当中的任何一个元素,必须是int或者float才行(注意是or的关系)

5. 给Schema传入一个字典对象(大部分使用Schema的场景都是传入字典对象,这个很重要)

Schema({'name': str, 'age': int}).validate({'name': 'foobar', 'age': 18})
{'age': 18, 'name': 'foobar'}
Schema({'name': str, 'age': int}).validate({'name': 'foobar'})
SchemaMissingKeyError: Missing keys: 'age'

首先,明确两个概念,Schema类传入的字典,称之为模式字典,valdiate方法传入的字典称之为数据字典。

首先,Schema会判断, 模式字典和数据字典的key是否完全一样,不一样的话直接抛出异常。如果一样,就去拿数据字典的value去验证模式字典相应的value,如果数据字典的全部value都可以验证通过的话才返回数据,否则抛出异常,是不是感觉这种验证顿时感觉清爽了呢?

6. faqs

Schema传入字典很好用,但是我有的数据是可选的,也就是说有的key可以不提供怎么办?

from schema import Optional, Schema

Schema({'name': str, Optional('age'): int}).validate({'name': 'foobar'})
{'name': 'foobar'}
Schema({'name': str, Optional('age', default=18): int}).validate({'name': 'foobar'})
{'age': 18, 'name': 'foobar'}

我想让Schema只验证传入字典中的一部分数据,可以有多余的key但是不要抱错,怎么做?

Schema({'name': str, 'age': int}, ignore_extra_keys=True).validate({'name': 'foobar', 'age': 100, 'sex': 'male'})
{'age': 100, 'name': 'foobar'}

Schema抛出的异常信息不是很友好,我想自定义错误信息,怎么办?

Schema自带的类(Use、And、Or、Regex、Schema等)都有一个参数error,可以自定义错误信息

Schema({'name': str, 'age': Use(int, error='年龄必须是整数')}).validate({'name': 'foobar', 'age': 'abc'})

SchemaError: 年龄必须是整数

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python常用知识梳理(必看篇)
Mar 23 Python
Python创建二维数组实例(关于list的一个小坑)
Nov 07 Python
浅谈python 里面的单下划线与双下划线的区别
Dec 01 Python
微信跳一跳自动运行python脚本
Jan 08 Python
Python Pandas找到缺失值的位置方法
Apr 12 Python
详解python多线程、锁、event事件机制的简单使用
Apr 27 Python
Python根据指定日期计算后n天,前n天是哪一天的方法
May 29 Python
用Python实现将一张图片分成9宫格的示例
Jul 05 Python
pytorch加载自定义网络权重的实现
Jan 07 Python
Python调用OpenCV实现图像平滑代码实例
Jun 19 Python
Python测试框架:pytest学习笔记
Oct 20 Python
pytorch finetuning 自己的图片进行训练操作
Jun 05 Python
Django用户认证系统如何实现自定义
Nov 12 #Python
Django自带用户认证系统使用方法解析
Nov 12 #Python
Django多数据库联用实现方法解析
Nov 12 #Python
Django数据库迁移常见使用方法
Nov 12 #Python
python爬虫中PhantomJS加载页面的实例方法
Nov 12 #Python
python调用win32接口进行截图的示例
Nov 11 #Python
python 下载m3u8视频的示例代码
Nov 11 #Python
You might like
PHP中判断变量为空的几种方法小结
2013/11/12 PHP
php实现下载限制速度示例分享
2014/02/13 PHP
php实现无限级分类(递归方法)
2015/08/06 PHP
在WordPress中安装使用视频播放器插件Hana Flv Player
2016/01/04 PHP
Laravel5框架添加自定义辅助函数的方法
2018/08/01 PHP
thinkPHP框架实现的简单计算器示例
2018/12/07 PHP
PHP实现数组根据某个字段进行水平合并,横向合并案例分析
2019/10/08 PHP
理解 JavaScript 预解析
2009/10/25 Javascript
JavaScript插入动态样式实现代码
2012/02/22 Javascript
再谈javascript面向对象编程
2012/03/18 Javascript
Jquery 模拟用户点击超链接或者按钮的方法
2013/10/25 Javascript
jQuery+AJAX实现网页无刷新上传
2015/02/22 Javascript
JavaScript学习笔记(三):JavaScript也有入口Main函数
2015/09/12 Javascript
Jquery跨域获得Json的简单实例
2016/05/18 Javascript
JQuery和PHP结合实现动态进度条上传显示
2016/11/23 Javascript
react开发中如何使用require.ensure加载es6风格的组件
2017/05/09 Javascript
JS实现队列的先进先出功能示例
2017/05/10 Javascript
Bootstrap4如何定制自己的颜色和风格
2018/02/26 Javascript
详解javascript 变量提升(Hoisting)
2019/03/12 Javascript
javascript中call()、apply()的区别
2019/03/21 Javascript
JS中注入eval, Function等系统函数截获动态代码
2019/04/03 Javascript
详解Node.js一行命令上传本地文件到服务器
2019/04/22 Javascript
vue cli3.0 引入eslint 结合vscode使用
2019/05/27 Javascript
微信小程序登录时如何获取input框中的内容
2019/12/04 Javascript
Python中在for循环中嵌套使用if和else语句的技巧
2016/06/20 Python
Python批量发送post请求的实现代码
2018/05/05 Python
使用PyInstaller将python转成可执行文件exe笔记
2018/05/26 Python
python和c语言的主要区别总结
2019/07/07 Python
Django rstful登陆认证并检查session是否过期代码实例
2019/08/13 Python
Python+Kepler.gl实现时间轮播地图过程解析
2020/07/20 Python
Django用户认证系统如何实现自定义
2020/11/12 Python
HTML5打开手机扫码功能及优缺点
2017/11/27 HTML / CSS
英国女士家居服网站:hush
2017/08/09 全球购物
信息技术专业大学生职业生涯规划书
2014/01/24 职场文书
小学语文复习计划
2015/01/19 职场文书
python如何正确使用yield
2021/05/21 Python