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中将单词首字母大写的capitalize()方法
May 18 Python
Python调用ctypes使用C函数printf的方法
Aug 23 Python
详解使用 pyenv 管理多个版本 python 环境
Oct 19 Python
Python模块搜索路径代码详解
Jan 29 Python
pycharm的console输入实现换行的方法
Jan 16 Python
Python实现串口通信(pyserial)过程解析
Sep 25 Python
python GUI编程(Tkinter) 创建子窗口及在窗口上用图片绘图实例
Mar 04 Python
python实现图像拼接功能
Mar 23 Python
Django form表单与请求的生命周期步骤详解
Jun 07 Python
Python实现http接口自动化测试的示例代码
Oct 09 Python
用python批量移动文件
Jan 14 Python
python如何获取网络数据
Apr 11 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
yii操作cookie实例简介
2014/07/09 PHP
php页面函数设置超时限制的方法
2014/12/01 PHP
thinkphp autoload 命名空间自定义 namespace
2015/07/17 PHP
thinkPHP中分页用法实例分析
2015/12/26 PHP
解决laravel session失效的问题
2019/10/14 PHP
javascript中的float运算精度实例分析
2010/08/21 Javascript
js为数字添加逗号并格式化数字的代码
2013/08/23 Javascript
IE中图片的onload事件无效问题和解决方法
2014/06/06 Javascript
jQuery滚动条插件nanoscroller使用指南
2015/04/21 Javascript
【经验总结】编写JavaScript代码时应遵循的14条规律
2016/06/20 Javascript
详解JavaScript跨域总结与解决办法
2016/10/31 Javascript
图文详解Javascript中的上下文和作用域
2017/02/15 Javascript
原生js实现吸顶效果
2017/03/13 Javascript
jstree单选功能的实现方法
2017/06/07 Javascript
JavaScript基本语法_动力节点Java学院整理
2017/06/26 Javascript
详解如何在vue项目中使用eslint+prettier格式化代码
2018/11/10 Javascript
在layui框架中select下拉框监听更改事件的例子
2019/09/20 Javascript
layui prompt 设置允许空白提交的方法
2019/09/24 Javascript
如何区分vue中的v-show 与 v-if
2020/09/08 Javascript
python实现跨文件全局变量的方法
2014/07/07 Python
Python实现Youku视频批量下载功能
2017/03/14 Python
对python程序内存泄漏调试的记录
2018/06/11 Python
Python 循环终止语句的三种方法小结
2019/06/24 Python
详解Python 多线程 Timer定时器/延迟执行、Event事件
2019/06/27 Python
python中tkinter窗口位置\坐标\大小等实现示例
2020/07/09 Python
HTML5本地存储之Database Storage应用介绍
2013/01/06 HTML / CSS
JBL英国官网:JBL UK
2018/07/04 全球购物
LACOSTE波兰官网:Polo衫、服装和鞋类
2020/09/29 全球购物
如果让你测试一台高速激光打印机,你都会进行哪些测试
2012/12/04 面试题
广播电视新闻学专业应届生求职信
2013/10/08 职场文书
人力资源管理毕业生自荐信
2013/11/21 职场文书
捐书倡议书
2014/08/29 职场文书
九年级语文教学反思
2016/03/03 职场文书
股东出资协议书
2016/03/21 职场文书
Windows下redis下载、redis安装及使用教程
2021/06/02 Redis
Spring Boot 排除某个类加载注入IOC的操作
2021/08/02 Java/Android