Files
djangoadmin-wiki/DjangoAdmin_Flask_AntdVue/zh/volume2/blueprint.md
T
2026-09-13 21:53:16 +08:00

218 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 路由注册(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 import response as R
from src.common.utils.request import parse_request_body, parse_batch_ids
# 定义 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 权限控制。