Flask 教程

Flask 视图函数

视图函数(View Functions) 是 Flask 应用的核心逻辑单元。简单来说,它是处理用户请求并生成响应的 Python 函数。

在 Flask 中,视图函数通常由 @app.route() 装饰器修饰,但理解它的本质和高级用法对于构建健壮的应用至关重要。


1. 视图函数的基本规则

一个标准的视图函数必须遵守以下两条铁律:

  1. 接收参数:可以接收来自 URL 的动态参数(如 <int:id>)。
  2. 返回响应:必须返回一个可以被转换为 HTTP 响应的对象(字符串、元组、Response 对象等)。
纯文本
plaintext
@app.route('/user/<name>')
def greet_user(name):  # name 是从 URL 捕获的参数
    return f'Hello, {name}!'  # 返回字符串,Flask 自动转为 200 OK 响应

2. 返回值的多种形式

Flask 非常灵活,视图函数可以返回多种类型的数据:

A. 简单字符串 (HTML)

纯文本
plaintext
@app.route('/')
def index():
    return '<h1>Hello World</h1>'

B. 元组 (自定义状态码和 Header)

格式:(response_body, status_code)(response_body, headers)

纯文本
plaintext
@app.route('/not-found')
def not_found():
    return 'Page not found', 404

@app.route('/custom')
def custom():
    return 'Created', 201, {'X-Custom-Header': 'Value'}

C. JSON 数据 (API 开发首选)

使用 jsonify 将字典或列表转换为 JSON 响应,并自动设置 Content-Type: application/json

纯文本
plaintext
from flask import jsonify

@app.route('/api/data')
def get_data():
    data = {"id": 1, "name": "Flask"}
    return jsonify(data)

D. Response 对象

当你需要精细控制响应(如设置 Cookie、修改 MIME 类型)时,手动创建 Response 对象。

纯文本
plaintext
from flask import make_response

@app.route('/cookie')
def set_cookie():
    resp = make_response('Cookie Set')
    resp.set_cookie('username', 'john')
    return resp

E. 重定向

纯文本
plaintext
from flask import redirect, url_for

@app.route('/old')
def old_page():
    return redirect(url_for('index')) # 302 临时重定向

3. 基于类的视图 (Pluggable Views)

当同一个 URL 需要根据不同的 HTTP 方法(GET, POST, PUT…)执行完全不同的逻辑时,使用大量的 if request.method == ... 会让代码变得丑陋。基于类的视图提供了更优雅的解决方案。

Flask 提供了 MethodView 类,它将 HTTP 方法映射为类中的方法名(小写)。

纯文本
plaintext
from flask.views import MethodView

class UserAPI(MethodView):
    def get(self, user_id=None):
        if user_id is None:
            # GET /users/ -> 获取用户列表
            return 'List of users'
        else:
            # GET /users/1 -> 获取特定用户
            return f'Details of user {user_id}'

    def post(self):
        # POST /users/ -> 创建新用户
        return 'User created'

    def delete(self, user_id):
        # DELETE /users/1 -> 删除用户
        return f'User {user_id} deleted'

# 注册路由
# as_view('endpoint_name') 将类转换为视图函数
user_view = UserAPI.as_view('user_api')

app.add_url_rule('/users/', view_func=user_view, methods=['GET', 'POST'])
app.add_url_rule('/users/<int:user_id>', view_func=user_view, methods=['GET', 'DELETE'])

优点

  • 代码结构清晰,每个 HTTP 方法对应一个独立的方法。
  • 易于继承和复用(例如创建一个通用的 BaseResourceView)。

4. 视图函数的生命周期钩子

有时你需要在视图函数执行之前之后做一些通用操作(如检查登录状态、记录日志)。Flask 提供了装饰器来实现这一点。

@app.before_request

在每次请求进入视图函数之前执行。如果返回了响应,则跳过视图函数直接返回该响应。

纯文本
plaintext
@app.before_request
def check_login():
    if request.endpoint != 'login' and 'user_id' not in session:
        return redirect(url_for('login'))

@app.after_request

在视图函数执行完毕,生成响应对象之后执行。必须接收并返回 response 对象。

纯文本
plaintext
@app.after_request
def add_header(response):
    response.headers['X-Frame-Options'] = 'DENY'
    return response

@app.teardown_request

无论请求是否成功,甚至在发生异常时,都会在请求结束时执行。常用于关闭数据库连接。

纯文本
plaintext
@app.teardown_request
def close_db(exception):
    db.close()

5. 最佳实践建议

  1. 保持视图函数轻量
    视图函数应该只负责“协调”:接收请求 -> 调用服务层/模型层处理业务 -> 返回响应。不要在视图函数里写复杂的 SQL 查询或业务逻辑。
  2. 使用蓝图模块化
    随着项目变大,不要把所有视图函数都放在 app.py。使用蓝图(Blueprints)将相关功能的视图函数分组(如 auth_views, api_views)。
  3. 统一错误处理
    不要在每个视图函数里 try-except。使用 @app.errorhandler 全局捕获异常。
纯文本
plaintext
   @app.errorhandler(500)
   def internal_error(error):
       db.session.rollback()
       return "Internal Server Error", 500
  1. 类型提示
    虽然 Flask 不强制,但给视图函数添加类型提示可以提高代码可读性和 IDE 支持。
纯文本
plaintext
   from flask import Response

   @app.route('/hello')
   def hello() -> Response:
       return jsonify({"msg": "hi"})

📝 总结

特性说明
核心职责接收 Request,返回 Response
简单场景使用函数 + @app.route
复杂/API 场景使用 MethodView 类视图
通用逻辑使用 before_request / after_request
返回值字符串、JSON (jsonify)、元组、Response 对象

掌握了视图函数,你就掌握了 Flask 应用的“大脑”。接下来,你想学习如何连接数据库让视图函数能存取数据,还是学习模板渲染让视图函数能返回漂亮的 HTML 页面?

发表回复

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