阶段 3插入 RBAC 测试数据合辑Django 系统阶段开发手册 阶段3 / 18 定位以自定义管理命令初始化 RBAC 测试数据并多渠道验证四张表中的数据关系 建议学时3–4 小时大家好我是小马不起床。阶段导语阶段 2 建成的 RBAC 四张表尚无数据本阶段向其中写入一批可支撑后续开发的测试数据包含五个环节1. 创建几个权限 2. 创建两个角色 3. 给角色分配权限 4. 创建两个系统用户 5. 验证数据库里已经有完整 RBAC 数据数据通过 Django 自定义管理命令init_rbac_data灌入命令使用get_or_create保证可重复执行。验证环节覆盖 MySQL 客户端、关联查询与 Django shell 三种途径。学习目标完成本阶段后应能够描述本阶段初始化数据的范围权限、角色、角色权限关系、用户四组数据创建management/commands包结构实现自定义管理命令init_rbac_data使用get_or_create与permissions.set实现幂等的数据初始化通过SELECT语句与多表 JOIN 查询验证sys_role_permission中的授权关系在 Django shell 中以对象方式验证用户、角色、权限的关联前置知识本阶段依赖阶段 2阶段 2创建 RBAC 四张表.md的产出前置条目具体要求四张表已创建rbac_db中存在sys_permission、sys_role、sys_role_permission、sys_user模型定义backend/rbac/models.py中四个模型类可正常导入SysUser.set_password可用阶段 1 基础可在backend目录执行python manage.py系列命令若上述内容尚未完成建议先完成阶段 2。目录本阶段要插入的数据创建初始化命令文件执行初始化命令检查数据库数据用关联查询看得更清楚用 Django shell 检查数据当前阶段完成后的数据关系阶段小结常见问题与排查下一阶段衔接1. 本阶段要插入的数据1.1 权限数据插入到sys_permission表数据如下permission_codepermission_namemenu_pathuser:list用户列表/usersuser:add新增用户/usersuser:delete删除用户/usersrole:list角色列表/roles1.2 角色数据插入到sys_role表数据如下role_coderole_nameadmin管理员user普通用户1.3 角色权限关系插入到sys_role_permission表。管理员拥有全部权限admin: - user:list - user:add - user:delete - role:list普通用户只拥有用户列表权限user: - user:list1.4 用户数据插入到sys_user表数据如下usernamepasswordroleadmin123456管理员zhangsan123456普通用户需要注意这里的 admin 是sys_user表里的业务用户不是 Django 后台/admin/的超级管理员。要点四组数据的写入顺序为权限 → 角色 → 授权关系 → 用户后者依赖前者权限以permission_code作为唯一标识授权关系引用该标识业务用户 admin 与后台超级管理员是两套互不相干的账号2. 创建初始化命令文件2.1 第 1 步创建目录确认当前位于rbac_project/backendmacOS / Linux 下执行mkdir-prbac/management/commandsWindows 的 PowerShell 环境下执行mkdir rbac\management\commands若提示目录已经存在不影响后续步骤。2.2 第 2 步创建空的__init__.pyDjango 需要识别这是一个 Python 包创建以下两个空文件backend/rbac/management/__init__.py backend/rbac/management/commands/__init__.py两个文件内部无需任何内容。目录结构随之变为backend/ └── rbac/ ├── management/ │ ├── __init__.py │ └── commands/ │ ├── __init__.py │ └── init_rbac_data.py ├── models.py ├── admin.py └── ...2.3 第 3 步创建初始化命令新建文件backend/rbac/management/commands/init_rbac_data.py写入以下完整代码fromdjango.core.management.baseimportBaseCommandfromrbac.modelsimportSysPermission,SysRole,SysUserclassCommand(BaseCommand):help初始化 RBAC 测试数据defhandle(self,*args,**options): 执行命令 python manage.py init_rbac_data # 1. 创建权限数据permissions_data[{permission_code:user:list,permission_name:用户列表,menu_path:/users,},{permission_code:user:add,permission_name:新增用户,menu_path:/users,},{permission_code:user:delete,permission_name:删除用户,menu_path:/users,},{permission_code:role:list,permission_name:角色列表,menu_path:/roles,},]permission_map{}foriteminpermissions_data:permission,createdSysPermission.objects.get_or_create(permission_codeitem[permission_code],defaults{permission_name:item[permission_name],menu_path:item[menu_path],},)permission_map[item[permission_code]]permissionifcreated:self.stdout.write(self.style.SUCCESS(f创建权限{permission.permission_name}))else:self.stdout.write(f权限已存在{permission.permission_name})# 2. 创建角色数据admin_role,admin_createdSysRole.objects.get_or_create(role_codeadmin,defaults{role_name:管理员,},)user_role,user_createdSysRole.objects.get_or_create(role_codeuser,defaults{role_name:普通用户,},)ifadmin_created:self.stdout.write(self.style.SUCCESS(创建角色管理员))else:self.stdout.write(角色已存在管理员)ifuser_created:self.stdout.write(self.style.SUCCESS(创建角色普通用户))else:self.stdout.write(角色已存在普通用户)# 3. 给管理员分配所有权限admin_role.permissions.set([permission_map[user:list],permission_map[user:add],permission_map[user:delete],permission_map[role:list],])self.stdout.write(self.style.SUCCESS(已给管理员分配权限user:list, user:add, user:delete, role:list))# 4. 给普通用户分配 user:list 权限user_role.permissions.set([permission_map[user:list],])self.stdout.write(self.style.SUCCESS(已给普通用户分配权限user:list))# 5. 创建 admin 用户ifnotSysUser.objects.filter(usernameadmin).exists():admin_userSysUser(usernameadmin,real_name管理员,phone13800000000,roleadmin_role,status1,)admin_user.set_password(123456)admin_user.save()self.stdout.write(self.style.SUCCESS(创建用户admin / 123456))else:self.stdout.write(用户已存在admin)# 6. 创建 zhangsan 用户ifnotSysUser.objects.filter(usernamezhangsan).exists():normal_userSysUser(usernamezhangsan,real_name张三,phone13900000000,roleuser_role,status1,)normal_user.set_password(123456)normal_user.save()self.stdout.write(self.style.SUCCESS(创建用户zhangsan / 123456))else:self.stdout.write(用户已存在zhangsan)self.stdout.write()self.stdout.write(self.style.SUCCESS(RBAC 测试数据初始化完成))self.stdout.write()self.stdout.write(当前测试账号)self.stdout.write(admin / 123456)self.stdout.write(zhangsan / 123456)要点management/commands两级目录及各自的__init__.py缺一不可否则命令无法被识别命令文件名init_rbac_data即后续 manage.py 子命令名权限与角色用get_or_create写入用户用filter(...).exists()判重后写入3. 执行初始化命令确认当前位于rbac_project/backend执行python manage.py init_rbac_data成功时输出类似创建权限用户列表 创建权限新增用户 创建权限删除用户 创建权限角色列表 创建角色管理员 创建角色普通用户 已给管理员分配权限user:list, user:add, user:delete, role:list 已给普通用户分配权限user:list 创建用户admin / 123456 创建用户zhangsan / 123456 RBAC 测试数据初始化完成 当前测试账号 admin / 123456 zhangsan / 123456重复执行该命令也不会重复创建数据因为代码使用了get_or_create其含义为如果数据不存在就创建 如果数据已经存在就直接使用已有数据。要点首次执行输出创建……“重复执行输出已存在……”两种情况均为正常幂等性来自get_or_create与用户写入前的存在性判断授权关系使用permissions.set每次执行都会按目标列表重置4. 检查数据库数据进入 MySQLmysql-uroot-p选择数据库USErbac_db;4.1 查看权限表SELECT*FROMsys_permission;应看到类似user:list user:add user:delete role:list4.2 查看角色表SELECT*FROMsys_role;应看到admin 管理员 user 普通用户4.3 查看用户表SELECTuser_id,username,real_name,phone,role_id,statusFROMsys_user;应看到admin zhangsan不直接查看 password 字段其中保存的是加密后的密码。4.4 查看角色权限关系SELECT*FROMsys_role_permission;管理员对应多条权限记录普通用户对应一条权限记录。要点用户表查询显式列出字段跳过加密的 password 列sys_role_permission中的记录条数即角色授权数量每张表的预期结果与第 1 章的数据设计一一对应5. 用关联查询看得更清楚执行下面 SQLSELECTr.role_name,p.permission_code,p.permission_nameFROMsys_role_permission rpJOINsys_role rONrp.role_idr.idJOINsys_permission pONrp.permission_idp.idORDERBYr.id,p.id;应看到类似管理员 user:list 用户列表 管理员 user:add 新增用户 管理员 user:delete 删除用户 管理员 role:list 角色列表 普通用户 user:list 用户列表这说明角色到权限角色 - 权限的关系已成功建立。要点中间表sys_role_permission通过role_id、permission_id两个外键关联主表JOIN 查询是核对授权关系最直观的手段结果共 5 行管理员 4 条、普通用户 1 条6. 用 Django shell 检查数据除 MySQL 外也可以直接用 Django 检查。执行python manage.py shell进入 shell 后输入fromrbac.modelsimportSysUser adminSysUser.objects.get(usernameadmin)admin.role.role_name结果应为管理员继续输入admin.role.permissions.all()可看到管理员拥有的权限。再查普通用户zhangsanSysUser.objects.get(usernamezhangsan)zhangsan.role.role_name结果应为普通用户再输入zhangsan.role.permissions.all()只应看到user:list退出 shellexit()要点对象路径user.role.role_name、role.permissions.all()直接体现模型层的关系设计shell 验证与 SQL 验证结果应一致二者互为印证模型间的反向与正向访问均基于阶段 2 定义的外键和多对多关系7. 当前阶段完成后的数据关系现在数据库中的关系为admin 用户 ↓ 管理员角色 ↓ user:list user:add user:delete role:list zhangsan 用户 ↓ 普通用户角色 ↓ user:list即admin 可以查看用户、新增用户、删除用户、查看角色 zhangsan 只能查看用户要点完整链路为用户 → 角色 → 权限两级传递admin 持有 4 项权限zhangsan 仅持有 user:list该关系图是阶段 4 权限判断逻辑要还原的目标阶段小结步骤说明数据设计4 项权限、2 个角色、5 条授权关系、2 个测试用户命令实现建立management/commands包编写init_rbac_data.py执行初始化python manage.py init_rbac_data重复执行保持幂等SQL 验证四张表分别SELECT并以 JOIN 查询核对角色-权限关系shell 验证通过模型对象访问 role 与 permissions 确认关联关系确认admin 拥有 4 项权限zhangsan 仅拥有 user:list常见问题与排查现象原因处理python manage.py init_rbac_data提示无法识别该命令management或commands目录缺少__init__.py或命令文件不在backend/rbac/management/commands/下按 2.2 的目录树核对包结构与文件名重复执行命令后权限输出已存在get_or_create判定数据已存在属预期行为无需处理该设计保证命令可重复执行sys_user表 password 字段显示为一长串加密文本写入时经过set_password加密属正常现象核对密码应使用check_password不要与明文比对JOIN 查询结果条数与预期不符授权数据未写入完整或执行命令前四张表尚未创建先确认阶段 2 迁移已完成再重新执行初始化命令shell 中admin.role访问报错用户记录未成功绑定角色用SELECT user_id, username, role_id FROM sys_user;核对role_id是否有值下一阶段衔接阶段 3 使四张 RBAC 表具备了完整的测试数据用户 → 角色 → 权限的数据链路已可查询验证。阶段 4阶段 4实现 RBAC 权限判断.md将基于这些数据实现权限判断逻辑给定一个登录用户沿本阶段建立的关系链取出其全部permission_code作为后续接口权限拦截与前端菜单控制的依据。