218 lines
8.0 KiB
Markdown
218 lines
8.0 KiB
Markdown
# 路由注册(Flask Blueprint)
|
||
|
||
Flask 使用 `Blueprint` 机制实现模块化路由注册。每个业务模块定义自己的 Blueprint,然后在路由注册中心统一挂载到应用。
|
||
|
||
## Blueprint 概念
|
||
|
||
`Blueprint` 是 Flask 提供的模块化路由组织方式。它允许将路由、视图函数、模板等组织在一个模块中,然后在应用中注册使用。
|
||
|
||
## 模块 Blueprint 定义
|
||
|
||
每个业务模块在 `router.py` 文件中定义自己的 Blueprint:
|
||
|
||
```python
|
||
# src/modules/system/position/router.py
|
||
|
||
from flask import Blueprint, request
|
||
from src.core.permission import check_permission
|
||
from src.core.response import R
|
||
from src.common.utils.request import parse_request_body, parse_id_list
|
||
|
||
# 定义 Blueprint
|
||
# 参数说明:
|
||
# - 'position': Blueprint 名称,用于内部标识
|
||
# - __name__: 模块名称,用于确定静态文件等资源路径
|
||
# - url_prefix='/position': 路由前缀,所有路由都会添加此前缀
|
||
position_blue = Blueprint('position', __name__, url_prefix='/position')
|
||
|
||
|
||
@position_blue.route('/page', methods=['GET'])
|
||
@check_permission('sys:position:page')
|
||
def page():
|
||
"""分页查询岗位列表"""
|
||
from src.modules.system.position.service import get_position_page
|
||
return get_position_page()
|
||
|
||
|
||
@position_blue.route('/detail/<int:id>', methods=['GET'])
|
||
@check_permission('sys:position:detail')
|
||
def detail(id):
|
||
"""查询岗位详情"""
|
||
from src.modules.system.position.service import get_position_detail
|
||
return get_position_detail(id)
|
||
|
||
|
||
@position_blue.route('/add', methods=['POST'])
|
||
@check_permission('sys:position:add')
|
||
def add():
|
||
"""新增岗位"""
|
||
from src.modules.system.position.service import add_position
|
||
from src.modules.system.position.schema import PositionForm
|
||
data = parse_request_body(request, PositionForm)
|
||
return add_position(data)
|
||
|
||
|
||
@position_blue.route('/update', methods=['PUT'])
|
||
@check_permission('sys:position:update')
|
||
def update():
|
||
"""更新岗位"""
|
||
from src.modules.system.position.service import update_position
|
||
from src.modules.system.position.schema import PositionForm
|
||
data = parse_request_body(request, PositionForm)
|
||
return update_position(data)
|
||
|
||
|
||
@position_blue.route('/delete/<int:id>', methods=['DELETE'])
|
||
@check_permission('sys:position:delete')
|
||
def delete(id):
|
||
"""删除岗位"""
|
||
from src.modules.system.position.service import delete_position
|
||
return delete_position(id)
|
||
|
||
|
||
@position_blue.route('/status', methods=['PUT'])
|
||
@check_permission('sys:position:status')
|
||
def status():
|
||
"""更新岗位状态"""
|
||
from src.modules.system.position.service import update_position_status
|
||
from src.modules.system.position.schema import PositionStatusForm
|
||
data = parse_request_body(request, PositionStatusForm)
|
||
return update_position_status(data)
|
||
```
|
||
|
||
## 路由注册中心
|
||
|
||
所有模块的 Blueprint 在 `src/routes/v1.py` 中统一注册:
|
||
|
||
```python
|
||
# src/routes/v1.py
|
||
|
||
from flask import Blueprint
|
||
|
||
from src.modules.system.position.router import position_blue
|
||
from src.modules.system.level.router import level_blue
|
||
from src.modules.system.dept.router import dept_blue
|
||
from src.modules.system.role.router import role_blue
|
||
from src.modules.system.menu.router import menu_blue
|
||
from src.modules.system.user.router import user_blue
|
||
# ... 其他模块导入
|
||
|
||
# 全部业务蓝图(按领域分组排序)
|
||
BLUEPRINTS = [
|
||
# 系统管理模块
|
||
user_blue, role_blue, menu_blue, dept_blue, position_blue, level_blue,
|
||
# 内容管理模块
|
||
# article_blue, category_blue, ...
|
||
# 监控管理模块
|
||
# job_blue, job_log_blue, ...
|
||
# ... 其他模块
|
||
]
|
||
|
||
|
||
def register_v1(app):
|
||
"""
|
||
注册 API v1 路由(所有业务蓝图挂载到 /api/v1)。
|
||
|
||
Args:
|
||
app: Flask 应用实例
|
||
"""
|
||
# 创建 v1 父 Blueprint
|
||
v1 = Blueprint('v1', __name__, url_prefix='/api/v1')
|
||
|
||
# 注册所有子 Blueprint
|
||
for blue in BLUEPRINTS:
|
||
v1.register_blueprint(blue)
|
||
|
||
# 将 v1 注册到应用
|
||
app.register_blueprint(v1)
|
||
|
||
return app
|
||
```
|
||
|
||
## 路由注册流程
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Flask 应用 (app) │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ v1 Blueprint (prefix: /api/v1) │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│
|
||
┌─────────────────────┼─────────────────────┐
|
||
▼ ▼ ▼
|
||
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||
│ position_blue │ │ level_blue │ │ dept_blue │
|
||
│ /position │ │ /level │ │ /dept │
|
||
└───────────────┘ └───────────────┘ └───────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
/api/v1/position/* /api/v1/level/* /api/v1/dept/*
|
||
```
|
||
|
||
## Blueprint 参数说明
|
||
|
||
```python
|
||
position_blue = Blueprint(
|
||
'position', # Blueprint 名称
|
||
__name__, # 模块名称
|
||
url_prefix='/position', # 路由前缀
|
||
# template_folder='templates', # 模板文件夹(可选)
|
||
# static_folder='static', # 静态文件夹(可选)
|
||
)
|
||
```
|
||
|
||
| 参数 | 说明 |
|
||
|:----|:----|
|
||
| `name` | Blueprint 名称,用于内部标识,必须唯一 |
|
||
| `import_name` | 模块名称,通常使用 `__name__` |
|
||
| `url_prefix` | 路由前缀,所有路由都会添加此前缀 |
|
||
| `template_folder` | 模板文件夹路径(相对于 Blueprint) |
|
||
| `static_folder` | 静态文件夹路径(相对于 Blueprint) |
|
||
|
||
## 路由装饰器
|
||
|
||
Flask 使用 `@blueprint.route()` 装饰器定义路由:
|
||
|
||
```python
|
||
@position_blue.route('/page', methods=['GET'])
|
||
def page():
|
||
"""分页查询岗位列表"""
|
||
pass
|
||
```
|
||
|
||
| 参数 | 说明 |
|
||
|:----|:----|
|
||
| `rule` | 路由规则,如 `/page`、`/detail/<int:id>` |
|
||
| `methods` | HTTP 方法列表,如 `['GET']`、`['POST']` |
|
||
|
||
### 动态路由参数
|
||
|
||
```python
|
||
@position_blue.route('/detail/<int:id>', methods=['GET'])
|
||
def detail(id):
|
||
"""查询岗位详情"""
|
||
pass
|
||
```
|
||
|
||
| 转换器 | 说明 | 示例 |
|
||
|:----|:----|:----|
|
||
| `<int:id>` | 整数参数 | `/detail/123` |
|
||
| `<string:name>` | 字符串参数(默认) | `/detail/abc` |
|
||
| `<float:price>` | 浮点数参数 | `/price/12.5` |
|
||
| `<uuid:id>` | UUID 参数 | `/detail/550e8400-e29b-41d4-a716-446655440000` |
|
||
|
||
## 开发要点
|
||
|
||
1. **每个模块定义自己的 Blueprint**:在 `router.py` 文件中定义
|
||
2. **统一在 `v1.py` 中注册**:将所有 Blueprint 添加到 `BLUEPRINTS` 列表
|
||
3. **使用 `check_permission` 装饰器**:实现 RBAC 权限控制
|
||
4. **路由前缀与模块目录名保持一致**:便于代码导航
|
||
5. **使用中文注释**:方便理解路由功能
|
||
|
||
## 总结
|
||
|
||
Flask Blueprint 是模块化路由组织的核心机制。每个业务模块定义自己的 Blueprint,在 `src/routes/v1.py` 中统一注册到 `v1` 父 Blueprint,最终挂载到 Flask 应用。通过 `url_prefix` 设置路由前缀,使用 `@blueprint.route()` 装饰器定义路由,结合 `check_permission` 实现 RBAC 权限控制。
|