【Dv3Admin】Django一键配置权限规则

源码中的角色---菜单---按钮---字段权限控制,往往是后台系统中最容易被忽略、却最容易出问题的部分。一旦权限粒度设计不清晰,就会出现按钮越权、字段泄露、前端渲染混乱等一系列连锁问题,这类问题通常并非单点错误,而是接口设计与数据组织方式叠加后的结果。

本文围绕一个实际存在的接口方法,完整拆解"角色---菜单---按钮---字段"这一权限聚合接口的实现方式,重点聚焦参数设计、查询链路与返回结构,理清数据是如何在一次请求中被组织并下发,为后续权限渲染与前端控制提供稳定基础。

文章目录

需求解析

该接口位于基于 Django REST Framework 的权限管理模块中,运行在已接入鉴权体系的后台服务内,通过自定义 ViewSet 暴露只读接口,用于权限配置与回显场景。
请求 get_role_menu_btn_field
解析 menuId / select
查询 MenuButton
按业务模式过滤按钮
序列化按钮权限
查询 MenuField
序列化字段权限
聚合返回数据

该界面用于角色权限配置场景,按钮与字段权限通过该接口进行回显与勾选。

功能实现

定位角色菜单按钮字段聚合接口

该方法定义在 RoleMenuButtonPermissionViewSet 中,作用是一次性返回某个菜单下可用的按钮权限与字段权限,避免前端拆分多次请求导致状态难以同步。

python 复制代码
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):

	......

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def get_role_menu_btn_field(self, request):
        """
        获取 角色-菜单-按钮-列字段
        :param request:
        :return:
        """

这一层使用 @action 装饰器暴露自定义接口,并通过 IsAuthenticated 保证只有登录态可访问,否则会导致权限配置数据被匿名获取。

解析请求参数与业务选择模式

接口通过 query_params 接收前端传入的菜单标识与业务模式,用于控制按钮筛选范围。

python 复制代码
        params = request.query_params
        menuId = params.get('menuId', None)
        select = params.get('select', None)
        select_dict = {
            "快速查询": ['查询', '详情'],
            "标准业务": ['查询', '详情', '新增', '编辑', '删除', '更新']
        }

这里将业务模式与按钮名称做成映射关系,避免前端直接拼接按钮名称条件,否则会导致筛选规则分散在多处,后期维护成本上升。

构建菜单按钮查询条件

按钮数据基于菜单进行过滤,同时在存在业务模式参数时进行名称模糊匹配。

python 复制代码
        menu_btn_queryset = MenuButton.objects.filter(menu_id=menuId)  # 按条件过滤 MenuButton
        if select:
            menu_btn_queryset = menu_btn_queryset.filter(
                reduce(or_, (Q(name__icontains=val) for val in select_dict[select]))
            )

reduce + or_ + Q 的组合用于动态拼接多个 OR 查询条件,使按钮筛选规则可以通过配置字典进行扩展,需要注意的是业务模式未命中时会直接抛异常,这一步不能省略参数校验,否则会导致运行期错误。

按钮数据序列化并绑定请求上下文

查询结果通过专用序列化器进行处理,统一输出结构。

python 复制代码
        menu_btn_serializer = RoleMenuButtonSerializer(menu_btn_queryset, many=True, request=request)

request 传入序列化器,通常用于字段级权限或动态字段控制,否则序列化阶段无法感知当前请求环境。

查询并序列化菜单字段权限

字段权限与按钮权限属于同一菜单维度,但模型与用途不同,因此采用独立查询与序列化。

python 复制代码
        menu_field_queryset = MenuField.objects.filter(menu_id=menuId)
        menu_field_serializer = RoleMenuFieldSerializer(menu_field_queryset, many=True, request=request)

字段权限通常用于控制表格列展示或表单可编辑性,与按钮权限解耦可以避免后期权限类型膨胀导致结构混乱。

统一返回权限聚合数据

接口最终将按钮权限与字段权限合并返回,供前端一次性消费。

python 复制代码
        return DetailResponse(data={'menu_btn': menu_btn_serializer.data, 'menu_field': menu_field_serializer.data})

这种聚合返回方式减少接口调用次数,同时保证按钮与字段权限处于同一菜单上下文,避免状态不一致问题。

完整代码如下

python 复制代码
from functools import reduce
from operator import or_
from django.db.models import Q


class RoleMenuButtonPermissionViewSet(CustomModelViewSet):

	......

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def get_role_menu_btn_field(self, request):
        """
        获取 角色-菜单-按钮-列字段
        :param request:
        :return:
        """
        params = request.query_params
        menuId = params.get('menuId', None)
        select = params.get('select', None)
        select_dict = {
            "快速查询": ['查询', '详情'],
            "标准业务": ['查询', '详情', '新增', '编辑', '删除', '更新']
        }

        menu_btn_queryset = MenuButton.objects.filter(menu_id=menuId)  # 按条件过滤 MenuButton
        if select:
            menu_btn_queryset = menu_btn_queryset.filter(
                reduce(or_, (Q(name__icontains=val) for val in select_dict[select]))
            )
        menu_btn_serializer = RoleMenuButtonSerializer(menu_btn_queryset, many=True, request=request)
        menu_field_queryset = MenuField.objects.filter(menu_id=menuId)
        menu_field_serializer = RoleMenuFieldSerializer(menu_field_queryset, many=True, request=request)
        return DetailResponse(data={'menu_btn': menu_btn_serializer.data, 'menu_field': menu_field_serializer.data})

总结

该接口的核心设计点在于围绕菜单维度,将按钮权限与字段权限进行聚合输出,通过业务模式参数控制按钮筛选范围,使权限配置具备可扩展性与可维护性,同时避免前端承担过多筛选逻辑。当前实现中对参数合法性的依赖较强,业务模式未命中时缺乏防御性处理,后期可通过白名单校验或默认策略兜底;如果进行重写,可考虑将按钮筛选规则抽象为配置表或策略类,降低 View 层复杂度。

这一实现方式在源码层面形成了一条清晰的权限数据下发链路,既保证了接口职责单一,又为前端权限渲染提供了稳定的数据基础,在多角色、多菜单系统中具备直接复用价值。

相关推荐
-杨豫1 小时前
ZLibrary反爬破解实战:从验证码到加密全突破
python
2301_818419012 小时前
Python内存管理机制:垃圾回收与引用计数
jvm·数据库·python
qq_417695052 小时前
构建一个桌面版的天气预报应用
jvm·数据库·python
cm6543202 小时前
Python在金融科技(FinTech)中的应用
jvm·数据库·python
小陈的进阶之路2 小时前
Selenium 常用操作 API
python·自动化·pytest
2301_816651222 小时前
如何从Python初学者进阶为专家?
jvm·数据库·python
2501_918126912 小时前
学习所有python写服务器的语句
服务器·人工智能·python·学习·个人开发
m0_569881472 小时前
使用Python自动收发邮件
jvm·数据库·python
极光代码工作室2 小时前
基于机器学习的房价预测系统设计与实现
人工智能·python·深度学习·机器学习