示例
介绍一个好用的定义restful框架,自动生成接口文档,规范定义入参出参
视图文件
import os
import json
from flask_restx import Namespace, fields, Model, reqparse, Resource
from models.error import CustomError
from models.map_res_model import res_model
# 创建一个 Flask-RESTx 命名空间
map_ns = Namespace("map", description="地图操作")
# 注册model
map_ns.models["res_model"] = res_model
# 定义请求解析器
get_map_parser = reqparse.RequestParser()
get_map_parser.add_argument('map_name', type=str, help="地图名称", required=True)
# 定义一个自定义验证函数,确保至少有一个参数被提供
def validate_at_least_one_param(args, keys):
if not any(args[key] for key in keys):
raise ValueError(f"必须提供 {keys} 的至少一个参数.")
# 校验文件路路径是否安全
def is_safe_path(base_path, target_path):
# 使用 os.path.abspath() 规范化路径
base_path = os.path.abspath(base_path)
target_path = os.path.abspath(os.path.join(base_path, target_path))
# 使用 os.path.commonprefix() 检查目标路径是否在基础路径下
return os.path.commonprefix([base_path, target_path]) == base_path
# 在视图函数中使用请求解析器并手动进行自定义验证
# 添加路径
@map_ns.route("/")
class PlatformMap(Resource):
# 解析参数
@map_ns.expect(get_map_parser)
# 添加注释
@map_ns.doc(description='通过地图名称或者id获取地图信息')
# 定义返回结构
@map_ns.marshal_with(res_model)
def get(self):
try:
args = get_map_parser.parse_args()
map_name = args.get("map_name")
folder_path = "static/upload_map/"
file_path = os.path.join(folder_path, map_name)
if os.path.exists(file_path) and is_safe_path(folder_path, map_name):
print(f"The file '{folder_path}' exists and is safe.")
else:
raise CustomError("文件不存在或文件路径错误", 404)
with open(file_path, "r") as f:
map_data = json.load(f)
res_data = {
"code": 200,
"message": "successful",
"data": map_data
}
return res_data, 200
except ValueError as ve:
return str(ve), 400 # 返回自定义错误消息和 HTTP 状态码
app 代码
from views.platfrom_map import map_ns
from flask import Flask, jsonify
from flask_restx import Api
from models.error import CustomError
app = Flask(__name__)
# 使用装饰器定义错误处理程序
@app.errorhandler(CustomError)
def handle_custom_error(error):
response = jsonify({"messags": error.args[0], "code": error.status_code})
response.status_code = error.status_code
return response
api = Api(app,
version='1.0',
title='MultiRobotSchedulingPlatform Api Doc',
description='MultiRobotSchedulingPlatform 接口文档',
doc='/doc'
)
api.add_namespace(map_ns, path='/map')
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0")
model 定义
from flask_restx import fields, Model
res_model = Model('res_model', {
'code': fields.Integer(required=True, description="接口code"),
'message': fields.String(required=True, description="接口信息"),
'data': fields.Nested(map_model),
})