在 Flask 中,请求(Request)和响应(Response)是 Web 应用与客户端(浏览器、App 或其他服务)交互的核心。
Flask 使用 Werkzeug 库来处理底层的 HTTP 协议细节,提供了非常 Pythonic 的对象来封装这些信息。
1. 请求对象 (Request)
request 是一个全局代理对象。虽然它在代码中看起来像全局变量,但在多线程环境下,Flask 通过“上下文机制”确保每个线程/协程看到的是属于当前请求的独立数据。
你需要从 flask 模块导入它:
from flask import request📥 获取数据的常用方式
| 数据来源 | 属性/方法 | 说明 | 示例 URL/Body |
|---|---|---|---|
| URL 查询参数 | request.args | 获取 ?key=value 形式的参数 | ?page=1&sort=desc |
| 表单数据 | request.form | 获取 POST 提交的表单 (application/x-www-form-urlencoded) | <form> 提交的数据 |
| JSON 数据 | request.get_json() | 获取 JSON 格式的请求体 (application/json) | {"name": "John"} |
| 文件上传 | request.files | 获取上传的文件对象 | <input type="file"> |
| Cookies | request.cookies | 获取客户端发送的 Cookie | dict-like object |
| Headers | request.headers | 获取 HTTP 请求头 | User-Agent, Authorization |
| Method | request.method | 获取请求方法 (GET, POST 等) | 'GET' |
💡 代码示例
from flask import Flask, request, jsonify
app = Flask(__name__)
# 1. 处理 GET 请求 (查询参数)
@app.route('/search')
def search():
# get('key', default) 如果 key 不存在,返回默认值,避免报错
keyword = request.args.get('keyword', '')
page = request.args.get('page', 1, type=int) # 自动转换为 int
return f'Searching for: {keyword}, Page: {page}'
# 2. 处理 POST 请求 (JSON 数据 - API 常用)
@app.route('/api/user', methods=['POST'])
def create_user():
data = request.get_json()
if not data or 'username' not in data:
return jsonify({"error": "Missing username"}), 400
username = data['username']
return jsonify({"message": f"User {username} created"}), 201
# 3. 处理 POST 请求 (表单数据)
@app.route('/login', methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
return f'Login attempt for: {username}'
# 4. 处理文件上传
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return 'No file part', 400
file = request.files['file']
if file.filename == '':
return 'No selected file', 400
# 保存文件
file.save(f'/safe/path/{file.filename}')
return 'File uploaded successfully'2. 响应对象 (Response)
视图函数的返回值会自动被 Flask 转换为响应对象。你可以返回多种类型,Flask 会智能处理:
- 字符串:自动转换为 HTML 响应,状态码 200。
- 元组:
(response_body, status_code)或(response_body, headers)。 - Response 对象:手动构建,用于精细控制。
- 字典/列表:如果安装了
flask.jsonify,通常建议显式使用jsonify转为 JSON。
📤 构建响应的常用方式
A. 简单返回 (最常用)
@app.route('/hello')
def hello():
return 'Hello World' # 默认 Content-Type: text/html; charset=utf-8B. 返回 JSON (API 开发标准)
使用 jsonify 不仅会将字典转为 JSON 字符串,还会自动设置 Content-Type: application/json。
from flask import jsonify
@app.route('/api/data')
def get_data():
data = {
"status": "success",
"items": [1, 2, 3]
}
return jsonify(data)C. 自定义状态码和 Header
@app.route('/created')
def created():
# 返回 201 Created 状态码
return "Resource Created", 201
@app.route('/custom-header')
def custom_header():
response = app.make_response("Custom Response")
response.headers['X-Custom-Header'] = 'MyValue'
return responseD. 重定向 (Redirect)
from flask import redirect, url_for
@app.route('/old-page')
def old_page():
# 302 临时重定向到首页
return redirect(url_for('index'))E. 错误响应
@app.errorhandler(404)
def not_found(error):
return jsonify({"error": "Not Found"}), 4043. 高级技巧:Make Response & After Request
🔧 make_response()
当你需要修改响应头(如设置 Cookie、CORS 头)时,使用 make_response 将普通返回值包装成响应对象。
from flask import make_response
@app.route('/set-cookie')
def set_cookie():
resp = make_response("Cookie Set!")
# 设置 Cookie: key, value, max_age(秒)
resp.set_cookie('username', 'john_doe', max_age=3600)
return resp🔄 @app.after_request
如果你希望每一个响应都带上相同的 Header(例如解决跨域问题 CORS),可以使用这个装饰器。
@app.after_request
def add_cors_headers(response):
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
return response⚠️ 常见陷阱与最佳实践
request.get_json()可能返回None:
如果请求头中没有Content-Type: application/json或者 Body 为空,它会返回None。务必先检查:
data = request.get_json(silent=True) # silent=True 出错时返回 None 而不是抛异常
if not data:
return "Invalid JSON", 400- 不要直接返回字典:
在旧版本 Flask 中,直接返回字典可能会报错或行为不一致。始终使用jsonify()。 - 大文件处理:
如果需要返回大文件或流式数据,不要一次性读入内存,使用Response的生成器模式或send_file/send_from_directory。 - 安全性:
- 永远不要信任
request.form或request.args中的数据,使用前必须进行验证和清洗(Sanitization)。 - 敏感信息不要放在 URL 参数中(因为 URL 会被记录在服务器日志里),应放在 POST Body 或 Header 中。
📝 总结流程图
客户端发起请求
↓
Flask 接收 → 创建 request 对象
↓
路由匹配 → 进入视图函数
↓
视图函数读取 request.args / .form / .get_json()
↓
业务逻辑处理...
↓
视图函数返回 (字符串 / jsonify / Response)
↓
Flask 转换为 HTTP 响应 → 发送给客户端掌握了请求与响应,你就打通了 Flask 应用的“任督二脉”。接下来,你想学习如何渲染 HTML 模板 (Jinja2) 让页面更漂亮,还是学习如何连接数据库存储这些数据?