【Dv3Admin】系统视图角色管理API文件解析

角色管理模块是后台系统权限控制的基础,基于角色分配权限可以有效管理用户访问范围与操作行为。通过细粒度划分角色,系统可兼顾灵活性与安全性,提升整体管理效率。

本文围绕 dvadmin/system/views/role.py,解析角色的增删改查、菜单按钮权限配置与数据范围控制的实现方式。结合源码细节探讨模块设计特点、接口设计思路及其在权限管理中的作用。

文章目录

role.py

本系统采用 Django + DRF 构建后台管理平台,聚焦角色管理、权限分配、系统配置模块。dvadmin/system/views/role.py 文件负责处理角色的增删改查、数据权限设置、菜单按钮权限配置。角色作为权限体系的核心,通过角色关联用户、菜单、字段、按钮,形成系统的权限控制基石。模块基于标准 ViewSet 开发,支持扩展性强的自定义逻辑,便于适配复杂的业务权限需求。

项目特点 描述
技术栈 Django + DRF
功能定位 后台管理系统角色模块,统一管理角色及其权限资源
设计原则 标准 RESTful,逻辑清晰,扩展性强
权限控制方式 基于角色的菜单、按钮、字段多维度权限分配

dvadmin/system/views/role.py 定义了角色管理模块的接口控制逻辑,包含角色的创建、查询、更新、删除,以及角色对应的菜单、按钮、字段权限的关联操作。模块通过重载父类方法,实现了角色数据权限动态调整(如绑定数据范围、部门权限),并提供专门接口处理角色授权、角色按钮权限配置。所有接口统一使用序列化器进行数据校验和格式化输出,保证数据一致性和接口规范性。

模块职责 说明
角色基本信息管理 包括角色名称、标识、描述等属性的增删改查
菜单权限分配 为角色绑定对应菜单,实现功能模块的访问控制
按钮权限分配 精细控制角色对页面功能按钮的可见与可操作性
字段权限配置 细粒度控制角色对模型字段的可读可写权限
数据范围权限 定义角色可操作数据的范围,如本人、部门、全部、自定义
动态接口授权 接口化处理角色权限调整,支持前端权限管理页面无刷新操作

在需要对系统用户进行权限分类管理,或者需要根据岗位分配不同访问能力的业务系统中,使用 dvadmin/system/views/role.py 定义的角色管理模块。例如:将用户按部门或职位分配为不同角色,每个角色对应不同的系统菜单、操作按钮、数据访问范围,确保系统安全性和高效性。角色管理作为 RBAC(基于角色的访问控制)实现的基础,是后台权限系统不可缺少的一环。

使用场景 说明
企业组织架构管理 不同部门设置不同角色,分配对应的菜单及操作权限
系统功能模块细粒度权限控制 角色绑定特定按钮权限,控制页面操作功能开关
数据安全合规场景 角色配置数据范围权限,防止越权访问敏感数据
行业系统定制化 针对行业需求自定义角色权限组合,提高系统灵活性
后台权限管理中心 统一配置用户角色及权限资源,减少维护成本

项目源码解析

角色基本信息序列化器

用于序列化角色对象,额外处理角色关联的用户列表,只保留用户ID、名称和所属部门名称。与 RoleUsers 表关联,主要用于角色管理列表展示和详情展示。

python 复制代码
class RoleSerializer(CustomModelSerializer):
    users = serializers.SerializerMethodField()

    @staticmethod
    def get_users(instance):
        users = instance.users_set.exclude(id=1).values('id', 'name', 'dept__name')
        return users

    class Meta:
        model = Role
        fields = "__all__"
        read_only_fields = ["id"]

角色创建与更新序列化器

专门处理角色新增和更新时的序列化,增加了对菜单、部门、按钮权限的嵌套展示,同时对角色名称和权限标识字段做唯一性校验。依赖 MenuSerializerDeptSerializerMenuButtonSerializer 子序列化器,保证数据准确性。

python 复制代码
class RoleCreateUpdateSerializer(CustomModelSerializer):
    menu = MenuSerializer(many=True, read_only=True)
    dept = DeptSerializer(many=True, read_only=True)
    permission = MenuButtonSerializer(many=True, read_only=True)
    key = serializers.CharField(
        max_length=50,
        validators=[CustomUniqueValidator(queryset=Role.objects.all(), message="权限字符必须唯一")]
    )
    name = serializers.CharField(max_length=50, validators=[CustomUniqueValidator(queryset=Role.objects.all())])

    class Meta:
        model = Role
        fields = '__all__'

角色菜单按钮权限序列化器

为角色返回对应菜单下的按钮权限列表。根据是否为超级管理员动态筛选按钮,普通用户只能看到自己有权限的按钮,用于菜单树权限勾选界面。

python 复制代码
class MenuPermissionSerializer(CustomModelSerializer):
    menuPermission = serializers.SerializerMethodField()

    def get_menuPermission(self, instance):
        is_superuser = self.request.user.is_superuser
        if is_superuser:
            queryset = MenuButton.objects.filter(menu__id=instance.id)
        else:
            menu_permission_id_list = self.request.user.role.values_list('permission', flat=True)
            queryset = MenuButton.objects.filter(id__in=menu_permission_id_list, menu__id=instance.id)
        serializer = MenuButtonSerializer(queryset, many=True, read_only=True)
        return serializer.data

    class Meta:
        model = Menu
        fields = ['id', 'parent', 'name', 'menuPermission']

菜单按钮权限勾选状态序列化器

用于前端权限设置界面,标记当前菜单是否有按钮权限绑定。超级管理员默认全部勾选,普通用户根据权限表判断是否勾选。

python 复制代码
class MenuButtonPermissionSerializer(CustomModelSerializer):
    isCheck = serializers.SerializerMethodField()

    def get_isCheck(self, instance):
        is_superuser = self.request.user.is_superuser
        if is_superuser:
            return True
        else:
            return MenuButton.objects.filter(
                menu__id=instance.id,
                role__id__in=self.request.user.role.values_list('id', flat=True)
            ).exists()

    class Meta:
        model = Menu
        fields = '__all__'

角色管理接口控制器

综合管理角色的增删改查、分配用户、移除用户等操作。继承自 CustomModelViewSetFastCrudMixinFieldPermissionMixin,具备自定义权限控制、快速增删改查功能,与用户、部门、菜单、按钮权限等模块协作密切。

python 复制代码
class RoleViewSet(CustomModelViewSet, FastCrudMixin, FieldPermissionMixin):
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    create_serializer_class = RoleCreateUpdateSerializer
    update_serializer_class = RoleCreateUpdateSerializer
    search_fields = ['name', 'key']

为某个角色动态添加或移除用户,支持双向操作。根据前端传来的 direction 参数决定是授权还是取消授权,修改 users_set 关系表。

python 复制代码
    @action(methods=['PUT'], detail=True, permission_classes=[IsAuthenticated])
    def set_role_users(self, request, pk):
        data = request.data
        direction = data.get('direction')
        movedKeys = data.get('movedKeys')
        role = Role.objects.get(pk=pk)
        if direction == "left":
            role.users_set.remove(*movedKeys)
        else:
            role.users_set.add(*movedKeys)
        serializer = RoleSerializer(role)
        return DetailResponse(data=serializer.data, msg="更新成功")

查询某个角色下已授权和未授权的用户,支持按用户姓名和部门筛选。常用于角色授权管理界面,提升权限分配体验。

python 复制代码
    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated, CustomPermission])
    def get_role_users(self, request):
        role_id = request.query_params.get('role_id', None)
        if not role_id:
            return ErrorResponse(msg="请选择角色")

        if request.query_params.get('authorized', 0) == "1":
            queryset = Users.objects.filter(role__id=role_id).exclude(is_superuser=True)
        else:
            queryset = Users.objects.exclude(role__id=role_id).exclude(is_superuser=True)

        if name := request.query_params.get('name', None):
            queryset = queryset.filter(name__icontains=name)

        if dept := request.query_params.get('dept', None):
            queryset = queryset.filter(dept=dept)

        page = self.paginate_queryset(queryset.values('id', 'name', 'dept__name'))
        if page is not None:
            return self.get_paginated_response(page)

        return SuccessResponse(data=page)

删除指定角色下的某个用户授权关系,简化了授权关系维护逻辑。用户通过 user_id 参数指定,防止误操作。

python 复制代码
    @action(methods=['DELETE'], detail=True, permission_classes=[IsAuthenticated, CustomPermission])
    def remove_role_user(self, request, pk):
        user_id = request.data.get('user_id', None)
        if not user_id:
            return ErrorResponse(msg="请选择用户")

        role = self.get_object()
        role.users_set.remove(*user_id)

        return SuccessResponse(msg="删除成功")

为指定角色批量添加多个用户,支持一次性多选操作,提升角色配置效率。通过 users_id 参数传递用户列表。

python 复制代码
    @action(methods=['POST'], detail=True, permission_classes=[IsAuthenticated, CustomPermission])
    def add_role_users(self, request, pk):
        users_id = request.data.get('users_id', None)
        if not users_id:
            return ErrorResponse(msg="请选择用户")

        role = self.get_object()
        role.users_set.add(*users_id)

        return DetailResponse(msg="添加成功")

应用案例

角色权限配置在后台系统中的权限管理落地实践

后台管理系统通常需要对用户的操作能力进行精细化限制,例如谁能访问某个菜单、点击哪个按钮、查看哪些数据字段。项目通过 dvadmin/system/views/role.py 模块构建了一套完整的角色权限控制体系,支持角色的增删改查、用户授权、菜单按钮绑定、数据范围设置等功能。管理员可通过后台角色配置界面,动态为角色分配权限,系统根据角色配置自动生效,确保安全性与灵活性并重。

功能点 内容描述
场景需求 对用户操作能力进行精细化限制,控制谁能访问某菜单、点击哪个按钮、查看哪些数据字段,确保系统安全性与灵活性。
核心模块 dvadmin/system/views/role.py:构建角色权限控制体系,统一管理权限分配与授权操作。
支持功能 - 角色管理:支持角色的增删改查功能。
- 用户授权:为角色动态分配用户,控制用户的权限范围。
- 菜单按钮绑定:角色可绑定菜单、按钮权限,控制访问范围和可操作项。
- 数据范围设置:支持为角色自定义数据范围权限(如部门、组织级别)。
权限数据管理 - 标准接口:提供角色权限数据的增删改查接口,供前端加载角色详情、用户授权状态与权限树。
- 多对多绑定:角色与菜单、按钮、字段、用户通过多对多关系绑定,高效维护权限结构。
控制器逻辑 - RoleViewSet:统一调度接口调用逻辑,通过自定义 action 实现动态授权与数据分配。
前端交互 - 动态加载角色权限树,展示绑定的菜单、按钮与字段权限。 - 支持在角色配置界面实时更新权限并立即生效。
应用场景 - 菜单权限管理 :控制用户可访问的菜单项。 - 按钮权限管理 :控制用户可操作的功能按钮。 - 字段权限管理:控制用户可查看或编辑的字段范围。
优势 - 提供精细化权限控制,确保系统安全性。 - 动态配置权限,提升管理效率与灵活性。
扩展能力 - 支持复杂的多角色、多权限层级场景。 - 可结合其他权限模块(如字段级权限、按钮级权限)构建完整权限体系。

模块中所有角色权限数据均通过标准接口进行增删改查,前端通过接口可加载角色详情、用户授权状态、权限树等内容。角色与菜单、按钮、字段、用户等模型之间通过多对多关系绑定,实现权限关系的高效维护。接口调用逻辑统一由 RoleViewSet 控制器调度,通过自定义 action 实现动态授权与数据分配。

角色权限配置的实际操作代码逻辑

以为某角色添加用户为例,管理员在权限管理页面选择角色并勾选多个用户,前端将以下请求发送至后端:

http 复制代码
POST /api/system/role/3/add_role_users/

{
  "users_id": [7, 8, 12]
}

后端调用如下方法,将这些用户添加至角色 ID 为 3 的角色中:

python 复制代码
def add_role_users(self, request, pk):
    users_id = request.data.get('users_id', None)
    role = self.get_object()
    role.users_set.add(*users_id)
    return DetailResponse(msg="添加成功")

若需移除角色中的用户,则调用:

http 复制代码
DELETE /api/system/role/3/remove_role_user/

{
  "user_id": 7
}

调用逻辑将目标用户从当前角色中解除绑定关系:

python 复制代码
def remove_role_user(self, request, pk):
    user_id = request.data.get('user_id', None)
    role = self.get_object()
    role.users_set.remove(*user_id)
    return SuccessResponse(msg="删除成功")

权限配置完成后,前端通过菜单权限树接口加载菜单及按钮列表:

http 复制代码
GET /api/system/menu/permissions/?role_id=3

系统根据用户是否为超级管理员自动判断勾选状态,返回如下格式的数据:

json 复制代码
[
  {
    "id": 5,
    "name": "系统管理",
    "menuPermission": [
      {"id": 21, "label": "新增"},
      {"id": 22, "label": "编辑"},
      {"id": 23, "label": "删除"}
    ]
  }
]

管理员可点击界面直接勾选按钮权限,系统保存后更新角色与 MenuButton 的关联关系,页面立即生效。整套机制将用户权限、页面元素、数据范围解耦,形成基于角色的多维权限系统,适用于各类企业、组织结构复杂的管理平台。

总结

模块基于标准 ViewSet 架构,结合序列化器实现角色及权限数据的统一校验与处理,保证接口一致性。增删改查、角色授权与按钮权限勾选功能通过自定义接口扩展,覆盖了常见权限管理场景,具备较好的灵活性与业务适配能力。

接口粒度较细但存在重复逻辑,部分校验可进一步抽象提升代码复用率。权限设置接口依赖数据库同步查询,面对大规模数据时可能存在性能瓶颈。若重写,可引入批量授权优化、异步处理及权限缓存机制,提升整体执行效率与扩展性。

相关推荐
noravinsc6 小时前
django 获取当前时间 格式 YYYY-MM-DD HH:Mm:ss
python·django·sqlite
大千AI助手6 小时前
django中如何解析content-type=application/json的请求
django·sqlite·json
码海漫游者810 小时前
让Python成为你的网站引擎:Django全栈开发初体验!!!
数据库·python·其他·django
Jamesvalley12 小时前
【Django】性能优化-普通版
python·性能优化·django
alpszero2 天前
使用VSCode开发Django指南
vscode·python·django·sqlite
伍六星2 天前
Flask和Django,你怎么选?
数据库·django·flask
Mr数据杨3 天前
【Dv3Admin】系统视图登录日志API文件解析
django
白嫖不白嫖3 天前
Django、Flask、FastAPI与Jupyter对比
django·flask·fastapi
Mr数据杨3 天前
【Dv3Admin】系统视图菜单管理API文件解析
django