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爬虫学习,轻松爬取大规模数据
Jan 03 Python
pycharm修改界面主题颜色的方法
Jan 17 Python
搭建python django虚拟环境完整步骤详解
Jul 08 Python
python按键按住不放持续响应的实例代码
Jul 17 Python
numpy np.newaxis 的实用分享
Nov 30 Python
python实现两个一维列表合并成一个二维列表
Dec 02 Python
Python数据可视化:饼状图的实例讲解
Dec 07 Python
python中的selenium安装的步骤(浏览器自动化测试框架)
Mar 17 Python
Python restful框架接口开发实现
Apr 13 Python
浅谈python处理json和redis hash的坑
Jul 16 Python
Python使用tkinter实现小时钟效果
Feb 22 Python
Python快速优雅的批量修改Word文档样式
May 20 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
IStream与TStream之间的相互转换
2008/08/01 PHP
SCP远程VPS快速搬家和WDCP升级php5.3安装memcached和eaccelerator教程
2017/07/27 PHP
php生成毫秒时间戳的实例讲解
2017/09/22 PHP
浅谈PHP array_search 和 in_array 函数效率问题
2019/10/15 PHP
laravel 框架结合关联查询 when()用法分析
2019/11/22 PHP
Apache+PHP+MySQL搭建PHP开发环境图文教程
2020/08/06 PHP
javascript显示选择目录对话框的代码
2008/11/10 Javascript
很好用的js日历算法详细代码
2013/03/07 Javascript
深入浅析JavaScript中的arguments对象(强力推荐)
2016/06/03 Javascript
jquery实现垂直和水平菜单导航栏
2020/08/27 Javascript
jQuery Ajax使用FormData对象上传文件的方法
2016/09/07 Javascript
使用jQuery卸载全部事件的思路详解
2017/04/03 jQuery
浅谈React碰到v-if
2018/11/04 Javascript
vue实现div拖拽互换位置
2020/07/29 Javascript
基于AngularJS拖拽插件ngDraggable.js实现拖拽排序功能
2019/04/02 Javascript
JavaScript实现烟花绽放动画效果
2020/08/04 Javascript
[11:42]2018DOTA2国际邀请赛寻真——OG卷土重来
2018/08/17 DOTA
Python数据类型详解(四)字典:dict
2016/05/12 Python
Python heapq使用详解及实例代码
2017/01/25 Python
Python原始字符串与Unicode字符串操作符用法实例分析
2017/07/22 Python
python 实现分页显示从es中获取的数据方法
2018/12/26 Python
python 通过类中一个方法获取另一个方法变量的实例
2019/01/22 Python
基于Python实现扑克牌面试题
2019/12/11 Python
Pycharm及python安装详细步骤及PyCharm配置整理(推荐)
2020/07/31 Python
Python调用Redis的示例代码
2020/11/24 Python
HTML5 通信API 跨域门槛将不再高、数据推送也不再是梦
2013/04/25 HTML / CSS
英国时尚泳装品牌:Maru Swimwear
2019/10/06 全球购物
当x.equals(y)等于true时,x.hashCode()与y.hashCode()可以不相等,这句话对不对
2015/05/02 面试题
考试不及格检讨书
2014/01/09 职场文书
应用化学专业职业生涯规划书
2014/01/22 职场文书
推广活动策划方案
2014/08/23 职场文书
广播稿:校园广播稿范文
2019/04/17 职场文书
大学生创业计划书常用模板
2019/08/07 职场文书
Feign调用全局异常处理解决方案
2021/06/24 Java/Android
详解Oracle数据库中自带的所有表结构(sql代码)
2021/11/20 Oracle
Django框架中视图的用法
2022/06/10 Python