为Flask应用中返回JSON的API定制错误处理程序
在Flask中为API路由单独定制JSON格式的错误处理
嘿,这个需求我之前做项目的时候刚好碰到过,Flask其实提供了好几种灵活的方式来区分网站路由和API路由的错误处理,下面给你分享几个实用的方案:
方法1:通过请求路径快速判断(零改动现有路由)
如果你不想调整现有的路由结构,这个方法最直接——在全局错误处理函数里判断请求路径是否属于API,返回对应的响应格式:
from flask import jsonify, render_template, request @app_instance.errorhandler(404) def handle_404(err): # 检查请求路径是否以/api开头 if request.path.startswith('/api'): return jsonify({ 'error': 'Not Found', 'message': '请求的API接口不存在', 'status_code': 404 }), 404 else: return render_template("err_404.html"), 404 @app_instance.errorhandler(500) def handle_500(err): if request.path.startswith('/api'): # 记得加上你的数据库回滚逻辑 db_instance.session.rollback() return jsonify({ 'error': 'Internal Server Error', 'message': '服务器发生未知错误', 'status_code': 500 }), 500 else: db_instance.session.rollback() return render_template("err_500.html"), 500
这个方案的优点是快速生效,不用改任何现有路由;缺点是如果后续API路径规则变化(比如不再以/api开头),你得同步修改判断条件。
方法2:用蓝图(Blueprint)分离API路由(推荐)
如果你的API路由数量较多,更推荐用蓝图把所有API路由统一管理,然后给蓝图单独注册错误处理——这样逻辑完全分离,后期维护起来特别方便:
第一步:创建API蓝图并注册路由
新建一个api.py文件,把所有API相关的内容放到这里:
# api.py from flask import Blueprint, jsonify from your_app_module import db_instance # 创建API蓝图,指定url前缀为/api api_bp = Blueprint('api', __name__, url_prefix='/api') # 注册你的API路由 @api_bp.route('/user') def get_user(): # 你的API业务逻辑 return jsonify({'data': 'user info'}) @api_bp.route('/weather') def get_weather(): # 你的API业务逻辑 return jsonify({'data': 'weather info'}) # 给蓝图注册专属的错误处理 @api_bp.errorhandler(404) def api_404(err): return jsonify({ 'error': 'Not Found', 'message': 'API接口不存在', 'status_code': 404 }), 404 @api_bp.errorhandler(500) def api_500(err): db_instance.session.rollback() return jsonify({ 'error': 'Internal Server Error', 'message': '服务器内部错误', 'status_code': 500 }), 500
第二步:在主应用中注册蓝图
回到你的主应用文件(比如app.py),注册这个API蓝图:
# app.py from flask import Flask, render_template from api import api_bp from your_db_module import db_instance app_instance = Flask(__name__) # 注册API蓝图 app_instance.register_blueprint(api_bp) # 保留原来的网站路由错误处理 @app_instance.errorhandler(404) def page_not_found_error(err): return render_template("err_404.html"), 404 @app_instance.errorhandler(500) def internal_server_error(err): db_instance.session.rollback() return render_template("err_500.html"), 500
这样一来,所有/api开头的请求都会触发蓝图里的错误处理,返回JSON格式;网站路由则继续使用原来的HTML错误页面,完美实现了分离。
方法3:自定义请求标记(灵活适配复杂场景)
如果你的API路径规则不固定,或者需要更灵活的判断逻辑,可以用自定义装饰器给API路由打上标记,然后在错误处理里识别这个标记:
第一步:编写自定义装饰器
from flask import g def mark_as_api(func): def wrapper(*args, **kwargs): # 在Flask的全局g对象中标记这个请求是API请求 g.is_api_request = True return func(*args, **kwargs) return wrapper
第二步:给API路由添加装饰器
@app_instance.route('/api/user') @mark_as_api def api_user(): return jsonify({'data': 'user info'}) @app_instance.route('/custom-api/weather') @mark_as_api def custom_api_weather(): return jsonify({'data': 'weather info'})
第三步:修改全局错误处理
@app_instance.errorhandler(404) def handle_404(err): # 检查g对象里的标记,默认是False if getattr(g, 'is_api_request', False): return jsonify({ 'error': 'Not Found', 'message': '请求的API资源不存在', 'status_code': 404 }), 404 else: return render_template("err_404.html"), 404
这个方案的优点是极度灵活,不管你的API路径是什么样的,只要加了@mark_as_api装饰器,就会返回JSON错误,特别适合路由规则复杂的场景。
内容的提问来源于stack exchange,提问作者sanskarsharma
相关产品推荐
相关产品推荐

