Flask路由基础 #

一、路由概念 #

1.1 什么是路由 #

路由是将URL映射到Python函数的机制。当用户访问某个URL时,Flask会根据路由规则找到对应的函数并执行。

text
用户请求 URL
    ↓
Flask路由系统
    ↓
匹配路由规则
    ↓
执行视图函数
    ↓
返回响应

1.2 路由的作用 #

作用 说明
URL映射 将URL映射到处理函数
参数提取 从URL中提取参数
方法过滤 限制HTTP请求方法
组织代码 按功能组织视图函数

二、基本路由 #

2.1 定义路由 #

python
from flask import Flask

app = Flask(__name__)

# 使用route装饰器定义路由
@app.route('/')
def index():
    return '首页'

@app.route('/about')
def about():
    return '关于页面'

@app.route('/contact')
def contact():
    return '联系方式'

2.2 路由规则 #

URL 视图函数 说明
/ index() 根路径
/about about() 关于页面
/contact contact() 联系方式

2.3 路由末尾斜杠 #

python
# 严格匹配(不带斜杠)
@app.route('/about')
def about():
    return '关于页面'
# 访问 /about 正常
# 访问 /about/ 返回404

# 带斜杠(自动重定向)
@app.route('/about/')
def about():
    return '关于页面'
# 访问 /about 自动重定向到 /about/
# 访问 /about/ 正常

2.4 查看所有路由 #

bash
# 命令行查看
flask routes

# 输出示例
# Endpoint  Methods  Rule
# --------  -------  ----------------
# about     GET      /about
# contact   GET      /contact
# index     GET      /
# static    GET      /static/<path:filename>
python
# 代码中查看
for rule in app.url_map.iter_rules():
    print(f'{rule.endpoint}: {rule.rule}')

三、动态路由 #

3.1 变量规则 #

python
# 字符串变量
@app.route('/user/<username>')
def show_user(username):
    return f'用户: {username}'

# 整数变量
@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f'文章ID: {post_id}'

# 多个变量
@app.route('/user/<username>/post/<int:post_id>')
def show_user_post(username, post_id):
    return f'用户 {username} 的文章 {post_id}'

3.2 类型转换器 #

转换器 说明 示例URL
string 接受任何不包含斜杠的文本(默认) /user/<string:name>
int 接受正整数 /post/<int:id>
float 接受正浮点数 /price/<float:p>
path 类似string,但接受斜杠 /file/<path:filename>
uuid 接受UUID字符串 /item/<uuid:id>

3.3 类型转换示例 #

python
@app.route('/user/<username>')
def user_profile(username):
    # username是字符串类型
    return f'用户名: {username}'

@app.route('/post/<int:post_id>')
def post_detail(post_id):
    # post_id是整数类型
    return f'文章ID: {post_id}'

@app.route('/price/<float:amount>')
def show_price(amount):
    # amount是浮点数类型
    return f'价格: ¥{amount:.2f}'

@app.route('/file/<path:filename>')
def download_file(filename):
    # filename可以包含斜杠
    return f'下载文件: {filename}'

@app.route('/item/<uuid:item_id>')
def show_item(item_id):
    # item_id是UUID类型
    return f'项目ID: {item_id}'

3.4 自定义转换器 #

python
from werkzeug.routing import BaseConverter

class ListConverter(BaseConverter):
    """列表转换器,将逗号分隔的字符串转为列表"""
    
    def to_python(self, value):
        return value.split(',')
    
    def to_url(self, values):
        return ','.join(str(v) for v in values)

# 注册转换器
app.url_map.converters['list'] = ListConverter

# 使用自定义转换器
@app.route('/tags/<list:tags>')
def show_tags(tags):
    return f'标签: {tags}'

访问 /tags/python,flask,web,输出:标签: ['python', 'flask', 'web']

四、URL规则 #

4.1 唯一URL重定向 #

python
@app.route('/projects/')
def projects():
    return '项目列表'

# 访问 /projects 会重定向到 /projects/
# 访问 /projects/ 正常显示

@app.route('/about')
def about():
    return '关于页面'

# 访问 /about 正常显示
# 访问 /about/ 返回404

4.2 URL构建 #

python
from flask import url_for

# url_for根据函数名生成URL
@app.route('/admin/')
def admin():
    return '管理后台'

with app.test_request_context():
    print(url_for('admin'))  # 输出: /admin/
    print(url_for('admin', page=1))  # 输出: /admin/?page=1

4.3 唯一路由名称 #

python
# 每个路由的endpoint必须唯一
# 默认endpoint是函数名

@app.route('/user/profile')
def profile():
    return '用户资料'

# 如果定义同名函数会报错
# @app.route('/user/info')
# def profile():  # 错误:函数名重复
#     return '用户信息'

# 可以手动指定endpoint
@app.route('/user/info', endpoint='user_info')
def profile_info():
    return '用户信息'

# 使用url_for
url_for('profile')  # /user/profile
url_for('user_info')  # /user/info

五、路由匹配顺序 #

5.1 匹配规则 #

Flask按照路由定义的顺序进行匹配,第一个匹配的路由会被使用。

python
# 更具体的路由应该放在前面
@app.route('/user/new')
def new_user():
    return '创建新用户'

@app.route('/user/<username>')
def show_user(username):
    return f'用户: {username}'

# 访问 /user/new 会匹配第一个路由
# 访问 /user/john 会匹配第二个路由

5.2 匹配优先级 #

python
# 静态路由优先于动态路由
@app.route('/user/admin')
def admin():
    return '管理员'

@app.route('/user/<username>')
def user(username):
    return f'用户: {username}'

# /user/admin 匹配第一个
# /user/other 匹配第二个

六、路由装饰器原理 #

6.1 装饰器本质 #

python
# route装饰器的简化实现
def route(self, rule, **options):
    def decorator(f):
        endpoint = options.pop('endpoint', None)
        self.add_url_rule(rule, endpoint, f, **options)
        return f
    return decorator

# 两种定义方式等价
@app.route('/hello')
def hello():
    return 'Hello!'

# 等价于
def hello():
    return 'Hello!'
app.add_url_rule('/hello', 'hello', hello)

6.2 使用add_url_rule #

python
def index():
    return '首页'

def about():
    return '关于页面'

app.add_url_rule('/', 'index', index)
app.add_url_rule('/about', 'about', about)

6.3 视图类 #

python
from flask.views import View

class UserView(View):
    methods = ['GET']
    
    def dispatch_request(self, username):
        return f'用户: {username}'

app.add_url_rule(
    '/user/<username>', 
    view_func=UserView.as_view('user_view')
)

七、路由分组 #

7.1 使用蓝图分组 #

python
from flask import Blueprint

# 创建蓝图
api = Blueprint('api', __name__, url_prefix='/api')

@api.route('/users')
def users():
    return '用户列表'

@api.route('/posts')
def posts():
    return '文章列表'

# 注册蓝图
app.register_blueprint(api)

# 访问 /api/users
# 访问 /api/posts

7.2 蓝图路由命名 #

python
from flask import Blueprint, url_for

auth = Blueprint('auth', __name__, url_prefix='/auth')

@auth.route('/login')
def login():
    return '登录'

@auth.route('/register')
def register():
    return '注册'

# 使用url_for时需要加蓝图前缀
url_for('auth.login')  # /auth/login
url_for('auth.register')  # /auth/register

八、路由最佳实践 #

8.1 命名规范 #

python
# 推荐:使用有意义的函数名
@app.route('/user/profile')
def user_profile():
    return '用户资料'

@app.route('/user/settings')
def user_settings():
    return '用户设置'

# 不推荐:使用无意义的函数名
@app.route('/user/profile')
def page1():
    return '用户资料'

8.2 URL设计原则 #

python
# 推荐:RESTful风格
@app.route('/users', methods=['GET'])
def list_users():
    return '用户列表'

@app.route('/users/<int:id>', methods=['GET'])
def get_user(id):
    return f'用户 {id}'

@app.route('/users', methods=['POST'])
def create_user():
    return '创建用户'

# 不推荐:动词式URL
@app.route('/get-users')
def get_users():
    return '用户列表'

@app.route('/create-user')
def create_user():
    return '创建用户'

8.3 路由组织 #

python
# 按功能模块组织路由
# auth/routes.py
auth = Blueprint('auth', __name__)

@auth.route('/login')
def login():
    pass

@auth.route('/register')
def register():
    pass

# user/routes.py
user = Blueprint('user', __name__)

@user.route('/profile')
def profile():
    pass

@user.route('/settings')
def settings():
    pass

九、路由调试 #

9.1 查看路由信息 #

python
# 打印所有路由
for rule in app.url_map.iter_rules():
    print(f'Endpoint: {rule.endpoint}')
    print(f'Rule: {rule.rule}')
    print(f'Methods: {rule.methods}')
    print('---')

9.2 路由冲突检测 #

python
# 检测重复的路由
routes = {}
for rule in app.url_map.iter_rules():
    key = (rule.rule, frozenset(rule.methods))
    if key in routes:
        print(f'警告:重复路由 {rule.rule}')
    routes[key] = rule.endpoint

9.3 路由测试 #

python
def test_routes():
    with app.test_client() as client:
        # 测试路由是否存在
        response = client.get('/')
        assert response.status_code == 200
        
        response = client.get('/user/test')
        assert response.status_code == 200
        
        response = client.get('/nonexistent')
        assert response.status_code == 404

十、总结 #

10.1 核心要点 #

要点 说明
路由定义 使用@app.route()装饰器
动态路由 使用converter:name语法
类型转换 string、int、float、path、uuid
路由匹配 按定义顺序,静态优先
蓝图分组 使用Blueprint组织路由

10.2 下一步 #

现在你已经了解了Flask路由基础,接下来让我们学习 URL规则与变量,深入了解动态路由和类型转换!

最后更新:2026-03-28