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