Flask路由默认只响应GET,因@app.route()不指定methods参数时仅注册GET方法;若用POST等其他方法访问会返回405错误,需显式声明methods=['GET','POST']或使用@app.post()等专用装饰器。

为什么 Flask 路由默认只响应 GET
Flask 的 @app.route() 装饰器如果不显式指定 methods 参数,**默认只注册 GET 方法**。当你用 POST、PUT 或其他方法访问该路由时,Flask 找不到匹配的处理函数,直接返回 405 Method Not Allowed —— 这不是你的代码报错,而是 Flask 的明确拒绝。
常见触发场景:
- 前端用
fetch()发POST请求,但后端路由没声明支持POST - 表单
<form method="POST"></form>提交到一个只写了@app.route('/login')的地址 - Postman 测试时手动选了
PUT,但路由只接受GET
如何在 @app.route() 中正确声明多个 HTTP 方法
必须通过 methods 参数传入一个字符串列表,大小写敏感,且必须是标准方法名(如 'POST',不是 'post')。
示例:
立即学习“Python免费学习笔记(深入)”;
@app.route('/api/user', methods=['GET', 'POST'])
def user_handler():
if request.method == 'GET':
return jsonify({'users': [...]})
elif request.method == 'POST':
data = request.get_json()
# 处理创建逻辑
return jsonify({'id': 123}), 201
关键点:
-
methods是必填关键字参数,不能写成位置参数 - 如果只支持
POST,必须写methods=['POST'],不能省略 - 允许的方法必须和实际请求方法完全一致;
'post'会失效 - 同一个 URL 可以有多个
@app.route(),但更推荐合并到一个视图函数里用request.method分支处理
用 @app.post() 等快捷装饰器更安全
Flask 2.0+ 提供了方法专用装饰器,语义清晰、不易漏写 methods,也避免手误拼错方法名。
等价写法:
@app.get('/status')
def get_status():
return 'OK'
<p>@app.post('/login')
def do_login():
data = request.form</p><h1>...</h1><p>@app.put('/api/item/<int:id>')
def update_item(id):
...
好处:
- 每个装饰器隐式绑定了对应方法,不会出现
405因为忘了写methods - IDE 和类型检查工具更容易识别意图
- 多个方法需共用逻辑时,仍建议回到
@app.route(methods=[...])+if/elif分支
调试时怎么快速确认是方法不匹配导致的 405
别急着改代码,先验证是不是路由注册问题:
- 运行
flask routes(确保已设FLASK_APP),看目标路径对应的Methods列是否包含你正在用的请求方法 - 在视图函数开头加
print(request.method, request.endpoint),确认请求确实到达了该函数(如果没打印,说明根本没匹配上路由) - 检查是否有蓝本(
Blueprint)未注册,或路由被url_prefix意外截断(比如注册了/api/v1/users,却请求了/users) - 注意:静态文件路由(
/static/...)和 Flask-Admin 等扩展自带的路由也可能拦截请求,造成看似“路由存在但报405”
最常被忽略的是:前端发的是 Content-Type: application/json,但后端用了 request.form —— 这不会导致 405,但会让 request.form 为空,容易误判为路由问题。


















