Python webargs 模块
一、安装
python3 -m pip install webargs
二、基础特性
# encoding=utf-8
from flask import Flask
from webargs import fields
from webargs.flaskparser import use_args
app = Flask(__name__)
app.route("/")
@use_args({
"name": fields.Str(required=True),
"age": fields.Int(required=True),
}, location='query')
def index(args):
print('args', args)
return "Hello " + args["name"]
if __name__ == "__main__":
app.run(debug=1)
2.1. 使用
2.1.1 通过装饰器
@use_args({
"name": fields.Str(required=True),
"age": fields.Int(required=True),
}, location='query')
- 第一个参数是需要获取的字段名,类型,是否必须等的定义
- location是指从哪里获取这些参数,默认是json,可选:
- 'querystring' (same as 'query')
- 'json'
- 'form'
- 'headers'
- 'cookies'
- 'files'
- 解析完后,把所有参数放在字典里面,传给下层函数
2.1.2 通过函数
args = parser.parse(user_args, request)
- 参数和装饰器一样,多了一传request
2.2 参数检查
from webargs import fields, validate
args_1 = {
# 必须参数,字符串类型
"username": fields.Str(required=True),
# validate
"password": fields.Str(validate=lambda p: len(p) >= 6),
"password": fields.Str(validate=validate.Length(min=6)),
# Default value when argument is missing
"display_per_page": fields.Int(missing=10),
# Repeated parameter, e.g. "/?nickname=Fred&nickname=Freddie"
"nickname": fields.List(fields.Str()),
# Delimited list, e.g. "/?languages=python,javascript"
"languages": fields.DelimitedList(fields.Str()),
# When value is keyed on a variable-unsafe name
# or you want to rename a key
"user_type": fields.Str(data_key="user-type"),
"start_day": fields.DateTime(required=True, format='%Y-%m-%d %X'),
"bool": fields.Bool(),
"email": fields.Email(),
"ip": fields.IP(),
"type": fields.Constant(constant='COMMON_TYPE'),
"money": fields.Decimal(),
"weight": fields.Float(),
"url": fields.URL(),
"uuid": fields.UUID(),
"raw": fields.Raw(),
}
- fields.Str 表示接收字符串参数
- required=True 表示必传
- validate=lambda p: len(p) >= 6 表示自定义检查函数。会把参数传递给该函数,该函数返回True表示检查通过,返回False或者抛出异常表示检查不通过
- 如果要对多个参数进行联合检查,需要在装饰器层架validate参数:
@use_args(args_1, validate=lambda args: len(args["username"]) < len(args["password"])) - 异常需要是
from webargs import ValidationError这个异常,不然会当程序异常处理
- 如果要对多个参数进行联合检查,需要在装饰器层架validate参数:
- 也可以用validate库里面的内置检查函数
- missing=10 表示如果没有入参,设置为默认值
- fields.List(fields.Str()) 表示列表型参数,列表的元素是字符串
- fields.DelimitedList(fields.Str()) 表示逗号型的列表参数
- data_key="user-type" 表示字段名修改,入参是user-type,在args字典会改为user_type
- fields.DateTime(required=True, format='%Y-%m-%d %X') 表示接收日期类型,并且格式需要符合,参数值会转换为datetime类型
- "bool": fields.Bool() 表示布尔类型,传1,0,true,false都能识别
- fields.Email() 只接收email,估计里面会有正则检查
- fields.IP() 只接收IP
- fields.Constant(constant='COMMON_TYPE') 常量参数,无论入参是什么值,type永远等于COMMON_TYPE
- fields.Decimal() 转换为Decimal类型
- fields.Float() 转换为float类型
- fields.URL() fields.UUID() 正则检查url格式或者uuid格式
- fields.Raw 不检查参数类型
内置参数检查
- validate=validate.Length(min=1,max=10) 检查字符串长度需要在某个区间
- validate=validate.OneOf(['male', 'female']) 入参需要在枚举里面
2.3 检查失败处理
如果参数检查失败,会返回422响应,但是不会提示哪个参数有问题。我们可以通过Flask的异常处理机制,捕获这个异常,然后构造我们想要的返回
@app.errorhandler(422) # 捕获422和400的异常码
@app.errorhandler(400)
def handle_error(err):
headers = err.data.get("headers", None)
messages = err.data.get("messages", ["Invalid request."])
print(headers)
print(messages) # {'json': {'password': ['Shorter than minimum length 6.']}}
return json.dumps({'err_code': 10000, 'err_msg': messages['json']})
- 从err里面获取信息,headers不知道有什么用的,message会有异常信息,例如不满足
validate=validate.Length(min=6)检查,就会返回{'json': {'password': ['Shorter than minimum length 6.']}} - 如果是主动抛出的ValidationError异常,message会包含ValidationError异常的内容
- 我们可以把这个参数检查信息返回给前端,提示前端哪个参数错误了。
messages['json']的json是location的key
2.4 嵌套参数
对于一些复杂的,有多重嵌套的参数
"name": fields.Nested(
{"first": fields.Str(required=True), "last": fields.Str(required=True)}
)
- 表示name是一个嵌套参数,也就是字典
- 然后里面需要要first key和last key
三、高级特性
3.1 自定义location
上面说了location支持query,json这些,也可以自定义
@parser.location_loader("data")
def load_data(request, schema):
data = {}
data.update({k: request.args.get(k) for k in request.args})
if request.json:
data.update({k: request.json.get(k) for k in request.json})
print(data, 'dataaaaa')
return data
parser.location = 'data' # 设置默认的location为data
- 上面定义了一个data的location,会合并args和json入参
- 把默认的location修改为data
也可以这样,这个是官方推荐方法:
@parser.location_loader("args_and_json")
def load_data(request, schema):
from webargs.multidictproxy import MultiDictProxy
newdata = request.args.copy()
if request.json:
newdata.update(request.json)
return MultiDictProxy(newdata, schema)
3.2 定义schema
除了可以通过字典定义args,也可以通过类:
from marshmallow import Schema
class UserSchema(Schema):
name = fields.Str(required=True)
age = fields.Int()
@app.route("/")
@use_args(UserSchema())
def index1(args):
print('args', args)
return "Hello "
3.3 未定义的参数处理
如果入参有未定义的参数,webargs默认会抛出422异常
from webargs.flaskparser import parser
import marshmallow
parser.unknown = marshmallow.EXCLUDE # 如果有未定义参数,不放到args参数,不抛异常
parser.unknown = marshmallow.INCLUDE # 如果有未定义参数,放到args参数,不抛异常
- 可以修改parse.unknown来修改策略。
- 也可以精确设置不同location的unknown策略
3.4 Flask的url参数
@app.route("/<int:id>/")
@use_args(UserSchema())
def index1(args, id):
print('args', args, id)
return "Hello "
- 如果需要用到Flask的url参数,就需要这样传递参数
Python webargs 模块的更多相关文章
- Python标准模块--threading
1 模块简介 threading模块在Python1.5.2中首次引入,是低级thread模块的一个增强版.threading模块让线程使用起来更加容易,允许程序同一时间运行多个操作. 不过请注意,P ...
- Python的模块引用和查找路径
模块间相互独立相互引用是任何一种编程语言的基础能力.对于“模块”这个词在各种编程语言中或许是不同的,但我们可以简单认为一个程序文件是一个模块,文件里包含了类或者方法的定义.对于编译型的语言,比如C#中 ...
- Python Logging模块的简单使用
前言 日志是非常重要的,最近有接触到这个,所以系统的看一下Python这个模块的用法.本文即为Logging模块的用法简介,主要参考文章为Python官方文档,链接见参考列表. 另外,Python的H ...
- Python标准模块--logging
1 logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等:相比print,具备如下优点: 可以通过设置不同 ...
- python基础-模块
一.模块介绍 ...
- python 安装模块
python安装模块的方法很多,在此仅介绍一种,不需要安装其他附带的pip等,python安装完之后,配置环境变量,我由于中英文分号原因,环境变量始终没能配置成功汗. 1:下载模块的压缩文件解压到任意 ...
- python Queue模块
先看一个很简单的例子 #coding:utf8 import Queue #queue是队列的意思 q=Queue.Queue(maxsize=10) #创建一个queue对象 for i in ra ...
- python logging模块可能会令人困惑的地方
python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...
- Python引用模块和查找模块路径
模块间相互独立相互引用是任何一种编程语言的基础能力.对于"模块"这个词在各种编程语言中或许是不同的,但我们可以简单认为一个程序文件是一个模块,文件里包含了类或者方法的定义.对于编译 ...
随机推荐
- jquery绑定事件时如何向事件函数里传参数
jquery绑定事件时如何向事件函数里传参数 jquery绑定事件时如何向事件函数里传参数 举例子说明: 步骤1: var button=$('<button type="button ...
- atexit模块介绍
atexit 模块介绍 python atexit 模块定义了一个 register 函数,用于在 python 解释器中注册一个退出函数,这个函数在解释器正常终止时自动执行,一般用来做一些资源清理的 ...
- iframe父子页面js之间的调用
父级页面:mian.html 子页面1:top.html 子页面2:index.html 页面关系 <div onclick="_top()">调用contentTop ...
- Defending Adversarial Attacks by Correcting logits
目录 概 主要内容 实验 Li Y., Xie L., Zhang Y., Zhang R., Wang Y., Tian Q., Defending Adversarial Attacks by C ...
- MQ消费失败,自动重试思路
在遇到与第三方系统做对接时,MQ无疑是非常好的解决方案(解耦.异步).但是如果引入MQ组件,随之要考虑的问题就变多了,如何保证MQ消息能够正常被业务消费.所以引入MQ消费失败情况下,自动重试功能是非常 ...
- 带SD读卡的USB HUB方案芯片MA8621|用于带读卡的USB HUB拓展坞方案芯片MA8621
MA8621是一款带SD读卡器控制器的USB 2.0高速3端口集线器方案芯片,主要用在USB TYPEC拓展坞或者USB typec扩展底座上面. 1. MA8621功能概述 MA8621是USB 2 ...
- Java初学者作业——定义英雄类(Hero),英雄类中的属性包括:姓名、攻击力、防御力、生命值和魔法值;方法包括:攻击、介绍。
返回本章节 返回作业目录 需求说明: 定义英雄类(Hero),英雄类中的属性包括:姓名.攻击力.防御力.生命值和魔法值:方法包括:攻击.介绍. 实现思路: 分析类的属性及其变量类型. 分析类的方法及其 ...
- python uwsgi 配置
启动:uwsgi --ini xxx.ini 重启:uwsgi --reload xxx.pid 停止:uwsgi --stop xxx.pid ini 文件 [uwsgi] chdir = /vag ...
- 【17MKH】我在框架中对.Net依赖注入的扩展
说明 依赖注入(DI)是控制反转(IoC)的一种技术实现,它应该算是.Net中最核心,也是最基本的一个功能.但是官方只是实现了基本的功能和扩展方法,而我呢,在自己的框架 https://github. ...
- visual studio code 修改工具栏风格
用windows版vscode的同学们是否发现它的工具栏是白色的跟整个界面看起来不太搭调,如下图: 其实要改变标题栏颜色也很简单,点击:文件> 首选项>设置 将 "window. ...