Flask 教程

Flask 请求与响应

在 Flask 中,请求(Request)响应(Response)是 Web 应用与客户端(浏览器、App 或其他服务)交互的核心。

Flask 使用 Werkzeug 库来处理底层的 HTTP 协议细节,提供了非常 Pythonic 的对象来封装这些信息。


1. 请求对象 (Request)

request 是一个全局代理对象。虽然它在代码中看起来像全局变量,但在多线程环境下,Flask 通过“上下文机制”确保每个线程/协程看到的是属于当前请求的独立数据。

你需要从 flask 模块导入它:

纯文本
plaintext
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">
Cookiesrequest.cookies获取客户端发送的 Cookiedict-like object
Headersrequest.headers获取 HTTP 请求头User-Agent, Authorization
Methodrequest.method获取请求方法 (GET, POST 等)'GET'

💡 代码示例

纯文本
plaintext
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 会智能处理:

  1. 字符串:自动转换为 HTML 响应,状态码 200。
  2. 元组(response_body, status_code)(response_body, headers)
  3. Response 对象:手动构建,用于精细控制。
  4. 字典/列表:如果安装了 flask.jsonify,通常建议显式使用 jsonify 转为 JSON。

📤 构建响应的常用方式

A. 简单返回 (最常用)
纯文本
plaintext
@app.route('/hello')
def hello():
    return 'Hello World'  # 默认 Content-Type: text/html; charset=utf-8
B. 返回 JSON (API 开发标准)

使用 jsonify 不仅会将字典转为 JSON 字符串,还会自动设置 Content-Type: application/json

纯文本
plaintext
from flask import jsonify

@app.route('/api/data')
def get_data():
    data = {
        "status": "success",
        "items": [1, 2, 3]
    }
    return jsonify(data)
C. 自定义状态码和 Header
纯文本
plaintext
@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 response
D. 重定向 (Redirect)
纯文本
plaintext
from flask import redirect, url_for

@app.route('/old-page')
def old_page():
    # 302 临时重定向到首页
    return redirect(url_for('index'))
E. 错误响应
纯文本
plaintext
@app.errorhandler(404)
def not_found(error):
    return jsonify({"error": "Not Found"}), 404

3. 高级技巧:Make Response & After Request

🔧 make_response()

当你需要修改响应头(如设置 Cookie、CORS 头)时,使用 make_response 将普通返回值包装成响应对象。

纯文本
plaintext
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),可以使用这个装饰器。

纯文本
plaintext
@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

⚠️ 常见陷阱与最佳实践

  1. request.get_json() 可能返回 None
    如果请求头中没有 Content-Type: application/json 或者 Body 为空,它会返回 None。务必先检查:
纯文本
plaintext
   data = request.get_json(silent=True) # silent=True 出错时返回 None 而不是抛异常
   if not data:
       return "Invalid JSON", 400
  1. 不要直接返回字典
    在旧版本 Flask 中,直接返回字典可能会报错或行为不一致。始终使用 jsonify()
  2. 大文件处理
    如果需要返回大文件或流式数据,不要一次性读入内存,使用 Response 的生成器模式或 send_file / send_from_directory
  3. 安全性
  • 永远不要信任 request.formrequest.args 中的数据,使用前必须进行验证和清洗(Sanitization)。
  • 敏感信息不要放在 URL 参数中(因为 URL 会被记录在服务器日志里),应放在 POST Body 或 Header 中。

📝 总结流程图

纯文本
plaintext
客户端发起请求
      ↓
Flask 接收 → 创建 request 对象
      ↓
路由匹配 → 进入视图函数
      ↓
视图函数读取 request.args / .form / .get_json()
      ↓
业务逻辑处理...
      ↓
视图函数返回 (字符串 / jsonify / Response)
      ↓
Flask 转换为 HTTP 响应 → 发送给客户端

掌握了请求与响应,你就打通了 Flask 应用的“任督二脉”。接下来,你想学习如何渲染 HTML 模板 (Jinja2) 让页面更漂亮,还是学习如何连接数据库存储这些数据?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注