在Django REST Framework中实现可配置的基于功能的角色权限扩展
调整角色权限体系以支持单个功能多操作的方案
核心思路
基于现有模型结构,通过扩展Permission模型的灵活性、强化Feature与Permission的关联,实现单个功能对应多自定义操作的权限控制,同时最大程度复用原有RoleFeatureAssociation和校验逻辑框架。
模型层调整
1. 重构Permission模型
将原有的CRUD枚举型Permission改为可配置的数据库实体,让每个Permission对应一个具体操作,并绑定到所属Feature:
# 示例(Django ORM) class Permission(models.Model): code = models.CharField(max_length=50, unique=True) # 操作唯一标识,如"order_create"、"order_accept" name = models.CharField(max_length=100) # 操作名称,如"创建订单"、"接受订单" feature = models.ForeignKey(Feature, on_delete=models.CASCADE, related_name="operations")
- 优势:支持任意自定义操作,不再局限于CRUD;通过
feature外键明确操作归属,避免权限混乱。
2. 复用并优化RoleFeatureAssociation
保留原模型结构,仅调整permissions字段的存储内容:
class RoleFeatureAssociation(models.Model): role = models.ForeignKey(Role, on_delete=models.CASCADE) feature = models.ForeignKey(Feature, on_delete=models.CASCADE) permissions = models.JSONField() # 存储对应Feature下的Permission.code列表,如["order_create", "order_split"] class Meta: unique_together = ("role", "feature") # 确保一个角色对一个功能仅存一条关联记录
- 无需修改表结构(若原字段为数组/JSON类型),仅变更存储的内容格式。
权限校验逻辑升级
原校验逻辑是验证角色对Feature是否拥有CRUD权限,现在调整为验证角色对指定Feature下的具体操作是否有权限:
def check_permission(role_id, feature_code, operation_code): # 1. 定位目标Feature try: feature = Feature.objects.get(code=feature_code) except Feature.DoesNotExist: return False # 2. 获取角色对该Feature的权限关联记录 association = RoleFeatureAssociation.objects.filter(role_id=role_id, feature=feature).first() if not association: return False # 3. 校验操作权限是否存在 return operation_code in association.permissions
- 调用方式示例:
check_permission(1, "order_management", "order_accept"),验证ID为1的角色是否拥有订单管理下的接受订单权限。
兼容性迁移(针对原有CRUD权限)
若系统已存在基于CRUD的权限数据,可通过批量迁移脚本将原有权限映射为新的操作权限:
# 迁移示例:将用户管理的CRUD权限转换为对应操作权限 user_feature = Feature.objects.get(code="user_management") # 创建对应操作权限 Permission.objects.get_or_create(code="user_create", name="创建用户", feature=user_feature) Permission.objects.get_or_create(code="user_read", name="查看用户", feature=user_feature) Permission.objects.get_or_create(code="user_update", name="更新用户", feature=user_feature) Permission.objects.get_or_create(code="user_delete", name="删除用户", feature=user_feature) # 更新RoleFeatureAssociation的permissions字段 for association in RoleFeatureAssociation.objects.filter(feature=user_feature): new_perms = [] if "create" in association.permissions: new_perms.append("user_create") if "read" in association.permissions: new_perms.append("user_read") # 同理处理update/delete association.permissions = new_perms association.save()
管理端适配
在角色权限配置界面,调整为:
- 选择Feature后,展示该Feature下所有已配置的操作权限(而非固定CRUD选项)
- 支持批量勾选操作权限,保存时将选中的Permission.code存入RoleFeatureAssociation的
permissions列表
内容的提问来源于stack exchange,提问作者Hamza Shah
相关产品推荐
相关产品推荐

