Flask 教程

Flask 路由

在 Flask 中,路由(Routing) 是 Web 框架最核心的机制之一。它的作用是建立 URL 路径Python 视图函数 之间的映射关系。简单来说,路由就是告诉 Flask:“当用户访问这个 URL 时,应该执行哪段代码”。

以下是 Flask 路由从基础到进阶的完整指南。


1. 基础路由

最基础的路由使用 @app.route() 装饰器,将 URL 绑定到函数上。

纯文本
plaintext
from flask import Flask

app = Flask(__name__)

# 当用户访问根路径 '/' 时,执行 index 函数
@app.route('/')
def index():
    return '欢迎来到首页!'

# 当用户访问 '/about' 时,执行 about 函数
@app.route('/about')
def about():
    return '这是关于我们的页面。'

2. 动态路由(变量规则)

很多时候,URL 中包含动态变化的部分(例如用户 ID、文章 ID)。Flask 允许你在 URL 中定义变量,并将其作为参数传递给视图函数。

语法:<变量名>

纯文本
plaintext
# 提取 URL 中的 username
@app.route('/user/<username>')
def show_user_profile(username):
    return f'用户: {username}'

转换器(Converters)

默认情况下,URL 中的变量是字符串。你可以使用转换器来指定变量的数据类型。如果类型不匹配,Flask 会返回 404。

语法:<转换器:变量名>

纯文本
plaintext
# int: 只匹配整数
@app.route('/post/<int:post_id>')
def show_post(post_id):
    # 这里的 post_id 已经是 int 类型,无需手动 int() 转换
    return f'文章 ID: {post_id}'

# float: 匹配浮点数
@app.route('/price/<float:amount>')
def show_price(amount):
    return f'价格: {amount}'

# path: 类似 string,但允许包含斜杠 '/' (常用于文件路径)
@app.route('/files/<path:filepath>')
def show_file(filepath):
    return f'文件路径: {filepath}'

# uuid: 匹配 UUID 字符串
@app.route('/uuid/<uuid:identifier>')
def show_uuid(identifier):
    return f'UUID: {identifier}'

3. 唯一斜杠行为(Trailing Slash)

这是一个新手经常踩坑的地方。Flask 对 URL 末尾的斜杠 / 有严格的处理规则,类似于文件系统中的“文件”和“目录”:

纯文本
plaintext
# 规则 1:路由末尾有斜杠 (类似目录)
@app.route('/users/')
def users():
    return '用户列表'
# 访问 /users 时,Flask 会自动 308 重定向到 /users/

# 规则 2:路由末尾没有斜杠 (类似文件)
@app.route('/profile')
def profile():
    return '个人主页'
# 访问 /profile/ 时,Flask 会直接返回 404 Not Found

最佳实践:保持团队规范统一。通常建议 API 接口不加末尾斜杠,而传统的网页路由加上末尾斜杠。


4. 指定 HTTP 方法

默认情况下,路由只响应 GET 请求。如果你需要处理表单提交(POST)或其他方法,必须显式指定 methods 参数。

纯文本
plaintext
from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 处理登录逻辑 (获取表单数据)
        username = request.form.get('username')
        return f'正在登录: {username}'
    else:
        # 返回登录表单页面
        return '显示登录表单 (GET)'

支持的常用方法:GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS


5. URL 构建(反向解析)⭐ 核心重点

永远不要在代码中硬编码 URL!
Flask 提供了 url_for() 函数,它通过视图函数的名字(即端点 Endpoint)来反向生成 URL。

纯文本
plaintext
from flask import url_for

@app.route('/')
def index():
    # 生成静态文件 URL
    css_url = url_for('static', filename='style.css')

    # 生成动态路由 URL (传入变量参数)
    user_url = url_for('show_user_profile', username='john_doe')
    post_url = url_for('show_post', post_id=42)

    return f"""
    CSS: {css_url}<br>
    User: {user_url}<br>
    Post: {post_url}
    """

为什么用 url_for

  1. 避免硬编码:如果以后把 /post/<int:id> 改成了 /article/<int:id>,只需要改路由装饰器,所有 url_for('show_post') 的地方会自动更新。
  2. 自动转义:它会自动处理 URL 中的特殊字符。
  3. 处理绝对路径:只需加上 _external=True 参数(如 url_for('index', _external=True)),就能生成带有域名的完整 URL(常用于发送邮件中的链接)。

6. 静态文件路由

Flask 会自动为你创建一个特殊的路由用于提供静态文件(CSS, JS, 图片等)。

默认情况下,你只需要在 url_for 中使用端点名 'static'

纯文本
plaintext
# 假设你的项目结构中有 static/images/logo.png
url_for('static', filename='images/logo.png')
# 生成的 URL 为: /static/images/logo.png

7. 进阶:基于类的视图 (Pluggable Views)

如果你有一个 URL 需要根据不同的 HTTP 方法(GET, POST)执行完全不同的逻辑,使用 if/else 会显得臃肿。Flask 提供了基于类的视图(MethodView)来优雅地解决这个问题。

纯文本
plaintext
from flask.views import MethodView

class UserAPI(MethodView):
    def get(self, user_id):
        if user_id is None:
            return '获取用户列表'
        else:
            return f'获取用户 {user_id} 的详情'

    def post(self):
        return '创建新用户'

    def delete(self, user_id):
        return f'删除用户 {user_id}'

# 将类视图注册到路由
# 注意:需要调用 .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'])

注:在实际大型项目中,基于类的视图常用于构建 RESTful API。


💡 路由最佳实践总结

  1. 端点命名:视图函数的名字(端点)应该具有描述性,因为 url_for 依赖它。
  2. 避免业务逻辑过重:路由/视图函数应该只负责“接收请求 -> 调用服务层处理 -> 返回响应”,不要把几百行的数据库查询和业务逻辑直接写在视图函数里。
  3. 善用蓝图:当路由超过 10 个时,立即使用 蓝图(Blueprint) 将路由拆分到不同的文件中(如 auth_routes.py, api_routes.py)。
  4. 统一 API 前缀:在注册 API 蓝图时,使用 url_prefix='/api/v1',方便后续版本迭代。

掌握了路由,你就掌握了控制 Web 应用流量走向的“方向盘”。接下来,你想了解如何处理路由中接收到的请求数据 (Request),还是学习如何返回模板 (Templates)JSON

发表回复

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