【转】Python Schema一种优雅的数据验证方式
转自 https://segmentfault.com/a/1190000011777230
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 Schema一种优雅的数据验证方式的更多相关文章
- sql有几种删除表数据的方式
有几种删除表数据的方式? truncate.delete和drop都可以删除数据. TRUNCATE TABLE删除表中的所有行,而不记录单个行删除操作. TRUNCATE TABLE 与没有 WHE ...
- Hive中的三种不同的数据导出方式介绍
问题导读:1.导出本地文件系统和hdfs文件系统区别是什么?2.带有local命令是指导出本地还是hdfs文件系统?3.hive中,使用的insert与传统数据库insert的区别是什么?4.导出数据 ...
- 2.Hive的几种常见的数据导入方式
好久没写Hive的那些事了,今天开始写点吧.今天的话题是总结Hive的几种常见的数据导入方式,我总结为四种:(1).从本地文件系统中导入数据到Hive表:(2).从HDFS上导入数据到Hive表:(3 ...
- SpringMVC 02: SpringMVC响应get和post请求 + 5种获取前端数据的方式
响应get和post请求 SpringMVC中使用@RequestMapping注解完成对get请求和post请求的响应 项目结构和配置文件与SpringMVC博客集中的"SpringMVC ...
- 014-HQL中级4-Hive中的三种不同的数据导出方式介绍
根据导出的地方不一样,将这些方式分为三种:(1).导出到本地文件系统:(2).导出到HDFS中:(3).导出到Hive的另一个表中.为了避免单纯的文字,我将一步一步地用命令进行说明. 一.导出到本地文 ...
- Python菜鸟之路:Django 数据验证之钩子和Form表单验证
一.钩子功能提供的数据验证 对于数据验证,django会执行 full_clean()方法进行验证.full_clean验证会经历几个步骤,首先,对于model的每个字段进行正则验证,正则验证通过后, ...
- 使用SpringBoot进行优雅的数据验证
JSR-303 规范 在程序进行数据处理之前,对数据进行准确性校验是我们必须要考虑的事情.尽早发现数据错误,不仅可以防止错误向核心业务逻辑蔓延,而且这种错误非常明显,容易发现解决. JSR303 规范 ...
- WPF数据验证方式
WPF有两种数据验证的方式: 1 在数据对象上进行验证:普通属性验证或者实现IDataErrorInfo接口 2 可以再绑定规则上进行验证:ExceptionValidationRule异常验证规则 ...
- iOS中几种常用的数据存储方式
自己稍微总结了一下下,方便大家查看 1.write直接写入文件的方法 永久保存在磁盘中,可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...
随机推荐
- CentOS7Linux中服务器LVS负载均衡、高可用集群搭建(NAT、DR);
目录 集群 声明 集群概念 集群特性 Web服务器并发相应瓶颈 集群的分类 LB实现方法: LVS集群 负载调度器 服务器池 共享存储 LVS负载均衡的三种模式 负载均衡 集群 声明 文档不断更新中. ...
- PostgreSQL-UNION与Order by 冲突
问题描述 union 连接的两个sql 都包含 order SELECT <property1>, <property2> FROM <table1> ORDER ...
- RabbitMQ入门教程(十五):普通集群和镜像集群
原文:RabbitMQ入门教程(十五):普通集群和镜像集群 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.c ...
- doT学习(三)之实战
案例一: <html> <head> <script id="headertmpl" type="text/x-dot-template&q ...
- [转载]Linux运行模式及紧急、救援模式
运行模式 在Linux中,存在一个叫init(initialize)的进程,其进程号是1,该进程存在一个对应的配置文件inittab,叫做系统的运行级别配置文件,位置在/etc/inittab.(但是 ...
- oracle使用between and边界问题
如果是只查询某两个月之间的数据,会默认从每个月的1号开始查,包前包后 eg:select * from test_hsj where regdate between to_date('2015-05' ...
- js 代码大全(各种方法、属性)
事件源对象event.srcElement.tagNameevent.srcElement.type捕获释放event.srcElement.setCapture(); event.srcElemen ...
- tomcat中部署多个项目,webAppRootKey 参数配置
在一个tomcat中部署多个项目时,需要在每个项目的web.xml中配置webAppRootKey参数,如下: <context-param> <param-name>webA ...
- 解决Kloxo出现Could not open database connection问题
当我们在使用或者运行kloxo面板的时候,可能会出现类似"Could not open database connection"错误提示,对于新手朋友来说肯定本身安装面板管理VPS ...
- Spring加载资源文件的方式
UrlResource 封装了java.net.URL,它能够被用来访问任何通过URL可以获得的对象,例如:文件.HTTP对象.FTP对象等.所有的URL都有个标准的 String表示,这些标准前缀可 ...