视图函数(View Functions) 是 Flask 应用的核心逻辑单元。简单来说,它是处理用户请求并生成响应的 Python 函数。
在 Flask 中,视图函数通常由 @app.route() 装饰器修饰,但理解它的本质和高级用法对于构建健壮的应用至关重要。
1. 视图函数的基本规则
一个标准的视图函数必须遵守以下两条铁律:
- 接收参数:可以接收来自 URL 的动态参数(如
<int:id>)。 - 返回响应:必须返回一个可以被转换为 HTTP 响应的对象(字符串、元组、Response 对象等)。
@app.route('/user/<name>')
def greet_user(name): # name 是从 URL 捕获的参数
return f'Hello, {name}!' # 返回字符串,Flask 自动转为 200 OK 响应2. 返回值的多种形式
Flask 非常灵活,视图函数可以返回多种类型的数据:
A. 简单字符串 (HTML)
@app.route('/')
def index():
return '<h1>Hello World</h1>'B. 元组 (自定义状态码和 Header)
格式:(response_body, status_code) 或 (response_body, headers)
@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。
from flask import jsonify
@app.route('/api/data')
def get_data():
data = {"id": 1, "name": "Flask"}
return jsonify(data)D. Response 对象
当你需要精细控制响应(如设置 Cookie、修改 MIME 类型)时,手动创建 Response 对象。
from flask import make_response
@app.route('/cookie')
def set_cookie():
resp = make_response('Cookie Set')
resp.set_cookie('username', 'john')
return respE. 重定向
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 方法映射为类中的方法名(小写)。
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
在每次请求进入视图函数之前执行。如果返回了响应,则跳过视图函数直接返回该响应。
@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 对象。
@app.after_request
def add_header(response):
response.headers['X-Frame-Options'] = 'DENY'
return response@app.teardown_request
无论请求是否成功,甚至在发生异常时,都会在请求结束时执行。常用于关闭数据库连接。
@app.teardown_request
def close_db(exception):
db.close()5. 最佳实践建议
- 保持视图函数轻量:
视图函数应该只负责“协调”:接收请求 -> 调用服务层/模型层处理业务 -> 返回响应。不要在视图函数里写复杂的 SQL 查询或业务逻辑。 - 使用蓝图模块化:
随着项目变大,不要把所有视图函数都放在app.py。使用蓝图(Blueprints)将相关功能的视图函数分组(如auth_views,api_views)。 - 统一错误处理:
不要在每个视图函数里 try-except。使用@app.errorhandler全局捕获异常。
@app.errorhandler(500)
def internal_error(error):
db.session.rollback()
return "Internal Server Error", 500- 类型提示:
虽然 Flask 不强制,但给视图函数添加类型提示可以提高代码可读性和 IDE 支持。
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 页面?