跳到主要内容

解析请求

前言

flask-restplus/restx 使用 reqparse.RequestParser 声明并解析请求参数,校验失败会自动返回 400。

新项目使用 flask_restx.reqparse,API 与 flask-restplus 一致。

基础参数

from flask_restplus import reqparse

parser = reqparse.RequestParser()
parser.add_argument("rate", type=int, help="Rate to charge for this resource")
args = parser.parse_args()

必需参数

parser.add_argument("name", type=str, required=True, help="Name cannot be blank")

required=True 时参数缺失会返回 400,help 内容作为错误消息。

多值和列表

# 同一参数可以出现多次,返回列表
parser.add_argument("tag", action="append")
# 默认值 + 指定默认列表
parser.add_argument("tag", action="append", default=[])

参数定位

参数定位指从哪取参数,默认从 request.valuesrequest.json 中取;可以通过 location 指定:

# 只从 POST body(表单)取
parser.add_argument("name", type=int, location="form")

# 只从查询字符串取
parser.add_argument("PageSize", type=int, location="args")

# 从请求头取
parser.add_argument("User-Agent", location="headers")

# 从 Cookie 取
parser.add_argument("session_id", location="cookies")

# 从文件上传取
parser.add_argument("picture", type=werkzeug.datastructures.FileStorage, location="files")

高级类型处理

# 类型转换函数
parser.add_argument("age", type=int)
parser.add_argument("ratio", type=float)
parser.add_argument("enabled", type=bool)

# 自定义类型转换
def parse_json(value: str) -> dict:
import json
return json.loads(value)

parser.add_argument("meta", type=parse_json)

解析器继承

base_parser = reqparse.RequestParser()
base_parser.add_argument("token", type=str, required=True, location="headers")

user_parser = base_parser.copy()
user_parser.add_argument("username", type=str, required=True)

文件上传

import werkzeug

upload_parser = reqparse.RequestParser()
upload_parser.add_argument(
"file",
type=werkzeug.datastructures.FileStorage,
location="files",
required=True,
)


@api.route("/upload")
class Upload(Resource):
def post(self):
args = upload_parser.parse_args()
uploaded_file = args["file"]
uploaded_file.save("/tmp/uploaded.txt")
return {"msg": "upload success"}

异常处理与错误消息

reqparse 校验失败时返回 400;也可以在业务代码中主动返回错误:

from flask_restplus import abort


@api.route("/item/<int:item_id>")
class Item(Resource):
def get(self, item_id):
if item_id != 1:
abort(404, f"Item {item_id} doesn't exist")
return {"id": item_id, "name": "apple"}

自定义错误响应格式(错误消息会以 {"message": ...}{"errors": {...}} 形式返回):

@api.errorhandler(ValueError)
def handle_value_error(error):
return {"message": str(error)}, 400

参考