Files
djangoadmin-wiki/DjangoAdmin_Flask_EleVue/zh/volume4/business/role.md
T
2026-09-12 23:12:15 +08:00

195 lines
6.6 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.
:::tip 角色管理
角色是 RBAC 权限模型的核心,连接用户和菜单(权限)。通过为角色分配菜单权限,再将角色分配给用户,实现灵活的权限管理。角色删除时需清理关联的用户角色和角色菜单数据,并即时失效受影响用户的权限缓存。
:::
## 模块结构
```
src/modules/system/role/
├── models.py # 角色模型
├── schema.py # 表单验证(WTForms)
├── repository.py # 数据访问层
├── service.py # 业务逻辑层(继承 BaseService)
└── router.py # 路由控制器
src/modules/association/role_menu/
├── models.py # 角色-菜单关联模型
├── repository.py # 关联数据访问
└── service.py # 关联业务逻辑
```
## 角色模型
```python
# src/modules/system/role/models.py
# ============================================================
# 角色模型
# ============================================================
class Role(BaseModel, BaseDB):
"""角色模型类"""
# ============================================================
# 表名配置
# ============================================================
__tablename__ = DB_PREFIX + "role"
__table_comment__ = "角色表"
# ============================================================
# 字段定义
# ============================================================
# 角色名称
name = Column(String(150), nullable=False, index=True, comment="角色名称")
# 角色编码
code = Column(String(30), nullable=False, index=True, comment="角色编码")
# 角色排序
sort = Column(Integer, default=0, server_default=text('0'), comment="角色排序")
# 角色备注
note = Column(String(255), nullable=True, comment="角色备注")
# ============================================================
# 内置方法
# ============================================================
def __str__(self):
"""返回角色名称作为字符串表示"""
return '角色{}:'.format(self.name)
```
## 角色-菜单关联
角色与菜单通过 `flask_role_menu` 关联表实现多对多关系:
```python
# src/modules/system/role_menu/models.py
# ============================================================
# 角色菜单关联模型
# ============================================================
class RoleMenu(BaseModel, BaseDB):
"""角色菜单关联模型类"""
# ============================================================
# 表名配置
# ============================================================
__tablename__ = DB_PREFIX + "role_menu"
__table_comment__ = "角色菜单关联表"
# ============================================================
# 字段定义
# ============================================================
# 角色ID
role_id = Column(Integer, default=0, server_default=text('0'), index=True, comment="角色ID")
# 菜单ID
menu_id = Column(Integer, default=0, server_default=text('0'), index=True, comment="菜单ID")
# ============================================================
# 内置方法
# ============================================================
def __str__(self):
"""返回角色ID作为字符串表示"""
return "角色菜单表{}".format(self.role_id)
```
## 自定义 Service
角色模块继承 BaseService,覆写删除前钩子处理关联清理和缓存失效:
```python
# src/modules/system/role/service.py
from src.common.base_service import BaseService
from src.modules.system.role.schema import RoleForm
from src.modules.system.role.repository import RoleRepository
from src.modules.association.user_role.repository import UserRoleRepository
from src.modules.system.menu.service import invalidate_user_cache
class RoleService(BaseService):
"""
角色服务类
继承 BaseService 获得标准 CRUD 能力,并扩展删除前清除用户权限缓存。
"""
repository = RoleRepository
form = RoleForm
model_name = "角色"
@classmethod
def before_delete(cls, ids):
"""
删除前钩子:清除该角色关联用户的权限缓存
Args:
ids: 待删除的角色ID列表
"""
for rid in ids:
for uid in UserRoleRepository.get_users_by_role(rid):
invalidate_user_cache(uid)
# 模块级代理函数
get_role_page = RoleService.get_page
get_role_detail = RoleService.get_detail
add_role = RoleService.add
update_role = RoleService.update
delete_roles = RoleService.remove
get_role_list = RoleService.get_list
```
## 删除与缓存清理
角色删除时,`before_delete` 钩子会先收集受影响用户并清理权限缓存:
```python
# src/modules/system/role/service.py
class RoleService(BaseService):
@classmethod
def before_delete(cls, ids):
"""
删除前钩子:清除该角色关联用户的权限缓存
在 BaseService.remove() 执行批量软删除之前调用,
确保权限缓存及时失效。
"""
for rid in ids:
for uid in UserRoleRepository.get_users_by_role(rid):
invalidate_user_cache(uid)
```
:::warning 删除顺序
`before_delete` 在 `BaseService.remove()` 的批量软删除**之前**执行,此时 UserRole 关联尚未删除,可以正常查询受影响用户。BaseService 的 `remove()` 方法会自动调用 `repository.batch_delete()` 完成软删除。
:::
## API 接口
| 接口 | 方法 | 权限节点 | 说明 |
|------|------|---------|------|
| `/api/v1/role/page` | GET | `sys:role:page` | 角色分页列表 |
| `/api/v1/role/list` | GET | `sys:role:list` | 角色列表(无分页) |
| `/api/v1/role/detail/{id}` | GET | `sys:role:detail` | 角色详情 |
| `/api/v1/role/add` | POST | `sys:role:add` | 新增角色 |
| `/api/v1/role/update` | PUT | `sys:role:update` | 编辑角色 |
| `/api/v1/role/delete/{id}` | DELETE | `sys:role:delete` | 删除角色 |
| `/api/v1/role/batchDelete` | DELETE | `sys:role:batchDelete` | 批量删除 |
| `/api/v1/role/auth` | POST | `sys:role:auth` | 分配菜单权限 |
## 前端权限分配
角色管理页面通常包含菜单树组件,用于勾选分配权限:
```vue
<el-tree
ref="menuTree"
:data="menuTreeData"
show-checkbox
node-key="id"
:default-checked-keys="checkedMenuIds"
/>
```
## 总结
角色管理模块具备以下特点:
```
1. RBAC 核心:连接用户和权限的桥梁
2. 继承 BaseService:标准 CRUD + 表单校验(WTForms)
3. before_delete 钩子:删除前清理关联用户的权限缓存
4. 灵活组合:一个角色可分配多个菜单,一个用户可拥有多个角色
```