【Django项目开发】角色管理模块的开发(八)

news2025/1/20 3:54:24

在这里插入图片描述


文章目录

  • 一、序列化器设计
    • 1、嵌套的序列化器设计
    • 2、普通的序列化类支持:新增、修改角色名、删除、查询
    • 3、用于给某一个角色批量授权的序列化
    • 4、用于给某一个角色单一授权,包括取消单一授权
  • 二、视图类设计
    • 1、包含的接口有哪些
    • 2、set_permission_to_role方法的实现
      • 2.1、ser.is_valid()
      • 2.2、授权和取消授权
      • 2.3、特别注意:
    • 3、特别注意
    • 4、完整代码

一、序列化器设计

1、嵌套的序列化器设计

需求:查询某个角色下的信息,包括该角色下的权限信息

a、自定义的序列化器类实际上也Field子类
b、所以自定义的序列化器类可以作为另外一个序列化器中的字段来使用

RolesModel和PermissionsModel两个模型类的关联字段为permissions
序列化中通过permissions字段接收
permissions=PermissionsSerializer(many=True,read_only=True):多对多的关联关系采用permissions,
many=True:因为是多对多的关系,数据可能有多条
如果是一对多的关联关系:permissions_set,

permission_serializer.py

class PermissionsSerializer(ModelSerializer):

    class Meta:
        model=PermissionsModel
        fields='__all__'

2、普通的序列化类支持:新增、修改角色名、删除、查询

roles_serializer.py

class BaseRolesSerializer(ModelSerializer):
    """
    普通的序列化类,支持:新增,修改角色名,删除、查询
    """
    permissions=PermissionsSerializer(many=True,read_only=True)
    class Meta:
        model=RolesModel
        fields='__all__'

3、用于给某一个角色批量授权的序列化

class RolesPartialSerializer(ModelSerializer):
    """
    用于给某一个角色批量授权的序列化
    """

    class Meta:
        model = RolesModel
        fields = ['id','permissions']

4、用于给某一个角色单一授权,包括取消单一授权

class RoleSetPermissionSerializer(Serializer):
    """
    用于给某一个角色单一授权,包括取消单一授权
    """
    #角色id
    role_id=IntegerField(write_only=True,required=True)
    #权限id
    permission_id=IntegerField(write_only=True,required=True)
    #是否授予权限还是取消;是(True);取消(False)
    is_create=BooleanField(write_only=True,required=True)

二、视图类设计

1、包含的接口有哪些

角色的增加:create
查询单个角色:retrieve
查询所有的角色:list
修改角色,仅仅修改角色的名字(属性):update
局部修改角色(角色的批量授权):partial_update
删除角色:destroy
批量删除角色:multiple_delete
给单个角色,单一授权:set_permission_to_role

上面的接口中,其中multiple_delete已经自定义抽象化,直接继承就行;
而set_permission_to_role需要在视图中实现

2、set_permission_to_role方法的实现

2.1、ser.is_valid()

ser.is_valid():作用是:对前端传递过来的数据进行校验;如果校验通过的,通过ser.validated_data可以获取到校验通过后的数据,为字典类型;
如果校验不通过,可以通过ser.errors属性获取错误信息,返回字典,包含了字段和字段的错误;如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。

2.2、授权和取消授权

role.permissions.add(permission)
role.permissions.remove(permission)

2.3、特别注意:

判断该权限对应的父菜单权限是否被授予,如果没有授权,需要把父菜单的权限也加进去

	@action(methods=['post'],detail=False)
    def set_permission_to_role(self,request,*args,**kwargs):
        ser=RoleSetPermissionSerializer(data=request.data)
        if ser.is_valid():
            #查询当前角色
            role=RolesModel.objects.get(id=ser.validated_data.get('role_id'))
            print('role:',role)
            #查询权限
            permission=PermissionsModel.objects.get(id=ser.validated_data.get('permission_id'))
            print('permission:',permission)
            if ser.validated_data.get('is_create'):
                #todo 判断该权限对应的父菜单权限是否被授予
                #todo 得到该权限对应的接口菜单  的父菜单
                parent_ids=MenuModel.objects.filter(id=permission.menu.id).values_list('parent',flat=True).all()
                if parent_ids:
                    parent_permission=PermissionsModel.objects.get(menu_id=parent_ids[0])
                    role.permissions.add(parent_permission)     #todo 把父菜单的权限也加进去
                print('role.permissions:',role.permissions)
                role.permissions.add(permission)    #把当前的权限授予当前的角色
                print('role.permissions:', role.permissions)

            else:#取消授权
                role.permissions.remove(permission)     #删除当前角色的当前权限
            result_ser=BaseRolesSerializer(instance=role)
            return Response(data=result_ser.data)

3、特别注意

角色数据库中有一个固定的角色:admin。这个角色代表所有权限,不能删除

需要重写destroy方法和multiple_delete方法

    #重写destroy函数,因为admin角色不能删除
    def destroy(self, request, *args, **kwargs):
        if self.get_object().name=='admin':
            return Response(data={'error':'admin角色不能删除'},status=status.HTTP_400_BAD_REQUEST)
        return super().destroy(request, *args, **kwargs)

    del_ids = openapi.Schema(type=openapi.TYPE_OBJECT, required=['ids'], properties={
        "ids": openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_INTEGER),
                              description="选择那些需要删除的ID(主键)")
    })

    @swagger_auto_schema(method='delete', request_body=del_ids, operation_description="批量删除菜单")  # 接口注释
    @action(methods=['delete'],detail=False)
    def multiple_delete(self,request,*args,**kwargs):
        delete_ids=request.data.get('ids')
        try:
            admin=RolesModel.objects.get(name='admin')
            if isinstance(delete_ids,list):
                if admin.id in delete_ids:
                    return Response(data={'error': 'admin角色不能删除'}, status=status.HTTP_400_BAD_REQUEST)
        except RolesModel.DoesNotExist as ex:
            pass

        return super().multiple_delete(request,*args,**kwargs)

4、完整代码

from rest_framework import viewsets
from erp_project.utils.base_views import MultipleDestroyMixin
from erp_system.models import RolesModel,PermissionsModel,MenuModel
from erp_system.serializer.role_serializer import RolesPartialSerializer,RoleSetPermissionSerializer,BaseRolesSerializer
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
from drf_yasg2 import openapi
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.permissions import IsAuthenticated

#角色数据库中有一个固定的角色:admin。这个角色代表所有权限,不能删除
class RolesView(viewsets.ModelViewSet,MultipleDestroyMixin):
    """
        create:
        角色--新增,

        角色新增,status:201(成功),return:新增角色信息

        list:
        查询所有的角色

        update:
        修改角色,仅仅修改角色的名字(属性)

        destroy:
        角色--删除 单个角色

        角色删除,status:204,return:None

        partial_update:
        局部修改角色(角色的批量授权),只能针对某一个角色一次性授权,之前的授权会被覆盖

        multiple_delete:
        角色--批量删除

        角色删除,status:204,return:None

        set_permission_to_role:
        给单个角色,单一授权。一次只能授予角色一个permission,也可以取消一个permission

        """
    queryset=RolesModel.objects.all()
    serializer_class = BaseRolesSerializer
    permission_classes = [IsAuthenticated]

    def get_serializer_class(self):
        if self.action=='partial_update':
            return RolesPartialSerializer
        elif self.action=='set_permission_to_role':
            return RoleSetPermissionSerializer
        else:
            return BaseRolesSerializer

    @action(methods=['post'],detail=False)
    def set_permission_to_role(self,request,*args,**kwargs):
        ser=RoleSetPermissionSerializer(data=request.data)
        if ser.is_valid():
            #查询当前角色
            role=RolesModel.objects.get(id=ser.validated_data.get('role_id'))
            print('role:',role)
            #查询权限
            permission=PermissionsModel.objects.get(id=ser.validated_data.get('permission_id'))
            print('permission:',permission)
            if ser.validated_data.get('is_create'):
                #todo 判断改权限对应的父菜单权限是否被授予
                #todo 得到该权限对应的接口菜单  的父菜单
                parent_ids=MenuModel.objects.filter(id=permission.menu.id).values_list('parent',flat=True).all()
                if parent_ids:
                    parent_permission=PermissionsModel.objects.get(menu_id=parent_ids[0])
                    role.permissions.add(parent_permission)     #todo 把父菜单的权限也加进去
                print('role.permissions:',role.permissions)
                role.permissions.add(permission)    #把当前的权限授予当前的角色
                print('role.permissions:', role.permissions)

            else:#取消授权
                role.permissions.remove(permission)     #删除当前角色的当前权限
            result_ser=BaseRolesSerializer(instance=role)
            return Response(data=result_ser.data)

    #重写destroy函数,因为admin角色不能删除
    def destroy(self, request, *args, **kwargs):
        if self.get_object().name=='admin':
            return Response(data={'error':'admin角色不能删除'},status=status.HTTP_400_BAD_REQUEST)
        return super().destroy(request, *args, **kwargs)

    del_ids = openapi.Schema(type=openapi.TYPE_OBJECT, required=['ids'], properties={
        "ids": openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_INTEGER),
                              description="选择那些需要删除的ID(主键)")
    })

    @swagger_auto_schema(method='delete', request_body=del_ids, operation_description="批量删除菜单")  # 接口注释
    @action(methods=['delete'],detail=False)
    def multiple_delete(self,request,*args,**kwargs):
        delete_ids=request.data.get('ids')
        try:
            admin=RolesModel.objects.get(name='admin')
            if isinstance(delete_ids,list):
                if admin.id in delete_ids:
                    return Response(data={'error': 'admin角色不能删除'}, status=status.HTTP_400_BAD_REQUEST)
        except RolesModel.DoesNotExist as ex:
            pass

        return super().multiple_delete(request,*args,**kwargs)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/152162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

听说……国产的领航辅助驾驶系统都很卷?

什么是城市NOA功能? 基于国产芯片的城市NOA功能有看点吗? 国产芯片发展到了什么阶段? 车上配的激光雷达是不是越多越好? 车企常吹的“数据驱动”、“中央计算” 究竟是真是假? ……最近,两家中国公司组CP 推…

基于ros将文件夹中的图像转换为bag包(c++版本)

一、前期工作创建工作空间 二、创建工作包 创建完成后,文件夹的格式为: 三、准备编译文件和代码 3.1 更换编译文件中的内容 将上图中的,CMakeLists.txt文件中的内容,替换为下面的内容 cmake_minimum_required(VERSION 3.0.2) p…

【漏洞复现】Yapi接口管理平台RCE漏洞汇总

文章目录前言YApi接口管理平台远程代码执行漏洞一、漏洞描述二、影响版本三、FOFA语句四、漏洞复现五、修复建议YApi NoSQL注入导致远程命令执行漏洞一、YApi介绍二、漏洞描述三、漏洞分析四、漏洞详情五、影响版本六、漏洞复现七、修复建议前言 本篇文章主要归纳总结YApi各版…

南邮数据结构

md文档网址:https://gitee.com/infiniteStars/wang-dao-408-notes/blob/master/408/数据结构.md 1 绪论 1.1算法的基本概念 程序与算法的区别和联系 联系:程序是计算机指令的有序集合,是算法用某种程序设计语言的表述,是算法在…

2023年如何搭建最小可行性的产品文档/产品手册?

在推出并击败竞争对手进入市场的竞赛中,很容易将“不必要的”任务(如文档)放在次要位置。但根据 Write the Docs 纪录片社区的说法,文档应该既是先导性的,也是参与性的。这意味着您应该在开始开发之前开始记录&#xf…

吊打高斯模糊的stackBlur加入OpenCV

stackBlur介绍 stackBlur 最近才加入到OpenCV中,将在下一个Relase版本(4.7)中出现。C用户可以尝试从源码编译OpenCV体验一下。Python 用户可以尝试用pip安装rolling版本的OpenCV: pip install opencv-python-rolling4.6.0.202210…

新手教程 | 常见的爬虫类型有哪些?

程序猿圈流传着一个神话级别的事:全公司仅靠1个人,每年就能转上1400多万美元。听起来天方夜谭一样,那他是如何做到的呢?看报道就会发现,他利用的是爬虫技术。 随着互联网的发展,从海量的互联网数据中&…

不可错过,Java程序员必备珍藏书单

不要因为迷茫,而停止了脚下的路。给大家推荐一份Java程序员必看的书单,豆瓣评分都挺不错的,往下看! 一、Java 基础篇书单 《Java编程思想》:从Java的基础语法到最高级特性(深入的面向对象概念、多线程、自…

煤矿智能化相关50项团体标准征求意见

智能化煤矿总体架构 原文地址:https://chinacs.scimall.org.cn/a3651.html 由煤矿智能化创新联盟等单位提出,中国煤炭学会归口,中煤科工集团常州研究院有限公司等单位起草的《煤矿通信接口与协议通用技术要求》50项团体标准已完成征求意见稿的…

用 Python 脚本实现电脑唤醒后自动拍照 截屏并发邮件通知

背景 背景是这样的, 我的家里台式机常年 休眠, 并配置了 Wake On Lan (WOL) 方便远程唤醒并使用. 但是我发现, 偶尔台式机会被其他情况唤醒, 这时候我并不知道, 结果白白运行了好几天, 浪费了很多电. 所以我的需求是这样的: 🤔 电脑唤醒后(可能是开机, 有可能是…

3款电脑必装软件,功能强大且免费,打死也舍不得卸载

闲话不多说,直接上狠货。 1、FlowUs息流 FlowUs息流是一款知识管理与协作平台,以云端笔记为载体,配合在线文档、知识库、文件夹等多形态功能,支持免费使用,极大提高个人与团队工作效率。支持多端同步使用,无…

STL空间配置器框架分析

目录 一、空间配置器概念 二、空间配置器的作用 三、内存池技术 四、空间配置器的实现原理 3.1 流程概述 3.2 一级空间配置器 3.3 二级空间配置器 3.3.1 二级空间配置器设计 3.3.2 内存碎片问题 一、空间配置器概念 即为各个容器高效的管理空间(空间的申请与回收)的。…

聊一聊双亲委派模式

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 说起双亲委派模型,不得不说一下类加载器。 类加载器是什么? 当我们编译Java类时,JVM会创建与平台和…

Allegro174版本新功能介绍之移动画布不闪屏设置

Allegro174版本新功能介绍之移动画布不闪屏设置 Allegro在升级到174版本后,在移动画布的时候,视图数据量比较大的情况,会出现闪屏现象 Allegro在切换到Open GL模式下,这个现象会有所缓解,具体操作如下 选择Setup选择User-preferences

【Ansible】ansible 基础知识

ansible 文章目录ansible一、ansible Ad-Hoc 命令1.命令格式2.模块类型3.联机帮助4.常用模块4.1 command & shell 模块4.2 script 模块4.3 copy 模块4.4 yum_repository4.5 yum 模块4.6 systemd 模块4.7 group 模块4.8 user 模块4.9 file 模块4.10 cron 模块4.11 template …

SIE高级副总裁:关于PS VR2定价、设计、内容的思考

2023年2月22日,索尼将正式推出次世代头显PS VR2,首发VR游戏将超过30款,其中包括热门游戏《GT赛车7 VR》。此外,PS5全球销量也已突破3000万。实际上距离索尼推出上一代PS VR,已经过去了6年时间,相比于Quest等…

M12269 支持PD3.1等快充协议、140W升降压3-8节多串锂电充放电移动电源管理IC

引言 在快充技术持续迭代升级的过程中,充电从小功率向中大功率的转变是最为明显的。支持的快充功率从最初的7.5W,已经向最高240W迈进。PD3.1协议的推出,进一步助力快充加速走向中大功率。新增三种固定电压档:28V(100-1…

VS1053 MP3模块介绍

VS1053MP3模块简介ATK-VS1053 MP3 MODULE是ALIENTEK推出的一款高性能音频编解码模块,该模块采用VS1053B作为主芯片,支持:MP3/WMA/OGG/WAV/FLAC/MIDI/AAC等音频格式的解码,并支持:OGG/WAV音频格式的录音,支持…

Mask RCNN网络源码解读(Ⅱ) --- ResNet、ResNeXt网络结构、BN及迁移学习

目录 1.ResNet简介 2.residual结构和ResNet-34详解 2.1 residual结构 2.2 Batch Normalization 3.迁移学习 4.ResNeXt网络结构 1.ResNet简介 ResNet在2015年由微软实验室提出,斩获当年lmageNet竞赛中分类任务第一名,目标检测第一名。获得coco数据…

信道模型:Rayleigh、Rician、卫星→地面

这里写目录标题比较C. Loo模型:直射阴影,多径不阴影Corazza模型:直射和多径都阴影Lutz模型:好坏2个状态Rayleigh and Rician 信道生成Shadowed-Rician 直射径 散射径[Secure Transmission in Cognitive Satellite Terrestrial Net…