支持Flask快速构建REST API 官方文档:https://flask-restful.readthedocs.io/en/latest/
快速安装
pip3 install flask-restful
使用示例
from flask import Flask, request, Response
from flask_restful import Resource, Api, abort
app = Flask(__name__)
api = Api(app)
todos = {}
"""继承资源类Resource,在类中定义方法"""
class TodoSimple(Resource):
"""restful 接口"""
def get(self, todo_id):
"""get请求-获取数据"""
if not todos.get(todo_id):
# abort(Response("查询失败", 404))
abort(404, message="Todo {} doesn't exist".format(todo_id))
return {todo_id: todos.get(todo_id)}
def put(self, todo_id):
"""put请求-更新数据"""
todos[todo_id] = request.form.get("data")
return {todo_id: todos[todo_id]}
def post(self, todo_id):
"""post请求-创建数据"""
todos[todo_id] = request.form.get("data")
return {
"status_code": 200,
"msg": "success"
}
def delete(self, todo_id):
"""delete请求-删除数据"""
todos[todo_id] = request.form.get("data")
if not todos.get(todo_id):
abort(Response('删除失败', 404))
del todos[todo_id]
return {
"status_code": 200,
"msg": "success"
}
"""向 api 添加资源"""
api.add_resource(TodoSimple, '/<string:todo_id>')
# 设置端点
# api.add_resource(TodoSimple, '/<string:todo_id>', endpoint="home")
if __name__ == "__main__":
app.run(debug=True)
参数解析-reqparse
parser = reqparse.RequestParser(bundle_errors=True)
parser.add_argument('data', type=str, help='请求参数必须是字符串', required=True, location='form')
args = self.parser.parse_args(strict=True)
通过flask_restful内置的reqparse,提供对请求数据验证的支持
- strict=True: 为强校验,包含解析器未定义的参数则抛出异常
- required=True: 可设置参数为必填参数
- location:可指定提取值的位置:form、args、headers、cookies、files
- bundle_errors=True:将错误捆绑在一起并一次发送回客户端
更多见:https://flask-restful.readthedocs.io/en/latest/reqparse.html#basic-arguments
# 使用实例
from flask_restful import Resource, Api, abort, reqparse
class TodoSimple(Resource):
"""restful 接口"""
# 请求参数解析,增加参数验证
parser = reqparse.RequestParser()
parser.add_argument('data', type=str, help='请求参数必须是字符串')
def put(self, todo_id):
"""put请求-更新数据"""
# strict=True 为强校验,包含解析器未定义的参数则抛出异常
args = self.parser.parse_args(strict=True)
# todos[todo_id] = request.form.get("data")
todos[todo_id] = args["data"]
return {todo_id: todos[todo_id]}, 201
def post(self, todo_id):
"""post请求-创建数据"""
args = self.parser.parse_args(strict=True)
todos[todo_id] = args["data"]
# todos[todo_id] = request.form.get("data")
return {
"status_code": 200,
"msg": "success"
}
输出字段-Fields
控制响应数据的呈现 1.可以在资源中使用任何您想要的对象(ORM 模型/自定义类/等) 2.还可以让您格式化和过滤响应,以防暴露内部数据结构 envelope:指定可选关键字参数包装结果输出 marshal_with装饰器:获取您的数据对象并应用字段过滤 更多见:https://flask-restful.readthedocs.io/en/latest/fields.html
from flask import Flask
from flask_restful import Resource, Api, abort, reqparse, fields, marshal_with
from typing import Optional
app = Flask(__name__)
api = Api(app)
resource_fields = {
'task': fields.String,
"todo_id": fields.String,
"status": fields.String(default="success")
}
class TodoDao(object):
"""响应参数类"""
def __init__(self, todo_id, task, status: Optional[str] = None):
self.todo_id = todo_id
self.task = task
self.status = status
class Todo(Resource):
"""数据格式化"""
# envelope指定可选关键字参数包装结果输出
# marshal_with装饰器:获取您的数据对象并应用字段过滤
# @marshal_with(resource_fields)
@marshal_with(resource_fields, envelope='resource')
def get(self, **kwargs):
"""get"""
return TodoDao(todo_id="todo2", task='Remember the milk')
"""向 api 添加资源"""
api.add_resource(Todo, "/todo_resource")
if __name__ == "__main__":
app.run(debug=True)
"""
# 响应示例
{
"resource": {
"task": "Remember the milk",
"todo_id": "todo2",
"status": "success"
}
}
"""
项目结构实践
/
/api_resource/ :存放接口资源
/__init.py
/common/ :存放公共配置
/config.py
/__init.py
/static/ :静态文件
/templates/ :模版
/utils/
/__init.py
/app.py :flask程序实例&链接mongo
/main.py :向api添加资源,启动flask主程序
# /utils/app.py
from flask_restful import Api
from logzero import logger
from flask_pymongo import PyMongo
from flask import Flask
from common import config
"""创建flask程序实例&链接mongo"""
app = Flask(__name__)
api = Api(app)
"""链接mongodb"""
app.config["MONGO_URI"] = ''.join([config.mongodb_str, "/", config.MONGODB_DBNAME, "?authSource=admin"])
mongo = PyMongo(app)
DB = mongo.db
logger.info(f"成功链接mongo: {DB}")
# /api_resource/api_test.py
from flask import jsonify
from flask_restful import Resource, abort
from logzero import logger
from utils.app import DB
class TestApi(Resource):
"""restful api"""
def get(self):
"""get"""
logger.info("restful test")
logger.info(DB.test.find_one({}))
return jsonify(message="success")
# /utils/main.py
"""向api添加资源,启动flask主程序"""
from api_resource.api_test import TestApi
from logzero import logger
from app import api, app
api.add_resource(TestApi, "/add_one")
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)