【DRF配置管理】如何实现RBAC页面菜单和按钮权限

原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。

DRF应用和管理

【DRF配置管理】Django安装DRF框架并生成openapi风格文档
【DRF配置管理】如何实现JWT身份验证
【DRF配置管理】如何使用序列化:验证码、注册和登录
【DRF配置管理】如何结合ORM实现排序、模糊搜索、范围查询
【DRF配置管理】如何在视图类使用get_objects()
【DRF配置管理】如何实现RBAC页面菜单和按钮权限
【DRF配置管理】如何建立coreapi风格api接口文档
【DRF配置管理】如何建立swagger风格api接口文档



一、常见用法

class Roles(models.Model):
    """角色表"""
    role_name = models.CharField(verbose_name='角色名称', max_length=32)
    permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permissions')

    creat_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    alter_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)

    class Meta:
        verbose_name = '权限组'
        verbose_name_plural = '权限组'
        app_label = 'users'

    def __str__(self):
        return self.role_name


class Permissions(models.Model):
    """权限"""
    method_choices = ((u'POST', u'增'), (u'DELETE', u'删'), (u'PUT', u'改'), (u'PATCH', u'局部改'), (u'GET', u'查'))
    name = models.CharField(max_length=30, verbose_name='权限名:')
    sign = models.CharField(max_length=30, unique=True, verbose_name='权限标识')
    menu = models.BooleanField(verbose_name='是否为菜单')  # True为菜单,False为接口
    method = models.CharField(max_length=8, blank=True, default='', choices=method_choices, verbose_name='方法')
    path = models.CharField(max_length=200, blank=True, default='', verbose_name='请求路径正则')
    desc = models.CharField(max_length=30, blank=True, default='', verbose_name='权限描述')
    weight = models.IntegerField(verbose_name='排序权重', default=0)
    pid = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父权限')

    creat_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    alter_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    objects = models.Manager()

    class Meta:
        verbose_name = '权限'
        verbose_name_plural = verbose_name
        ordering = ['id']
        app_label = 'users'

    def __str__(self):
        if self.pid:
            return '二级菜单:' + self.name
        else:
            return '一级菜单:' + self.name

二、实时计算边界

class UserSerializer(ModelSerializer):
    permissions = serializers.SerializerMethodField()

    class Meta:
        model = LoginUser
        fields = ['uuid', 'username', 'phone', 'user_permissions', 'permissions']

    def get_permissions(self, obj):
        permissions = obj.roles.order_by('-permissions__pid__weight', '-permissions__weight').values(
            'permissions__id',
            'permissions__menu',
            'permissions__name',
            'permissions__path',
            'permissions__weight',  # 权重

            'permissions__pid__id',  # 一级菜单
            'permissions__pid__menu',  # 一级菜单
            'permissions__pid__name',  # 一级菜单
            'permissions__pid__path',  # 一级菜单
            'permissions__pid__weight',  # 一级菜单权重
        ).distinct()
        permission_list = []  # 全部权限
        permission_menu_dict = {}  # 菜单权限
        for permission in permissions:
            # 获取一级菜单并把二级菜单作为children
            if permission.get('permissions__pid__menu'):
                if permission_menu_dict.get(str(permission.get('permissions__pid__id'))):
                    permission_menu_dict[str(permission.get('permissions__pid__id'))]['children'].append({
                        'name': permission.get('permissions__name'),
                        'path': permission.get('permissions__path'),
                        'weight': permission.get('permissions__weight')
                    })
                else:
                    permission_menu_dict[str(permission.get('permissions__pid__id'))] = {
                        'name': permission.get('permissions__pid__name'),
                        'path': permission.get('permissions__pid__path'),
                        'weight': permission.get('permissions__pid__weight'),
                        'children': [{
                            'name': permission.get('permissions__name'),
                            'path': permission.get('permissions__path'),
                            'weight': permission.get('permissions__weight')
                        }]
                    }
            elif permission.get('permissions__menu') and not permission_menu_dict.get(
                    str(permission.get('permissions__id'))):
                permission_menu_dict[str(permission.get('permissions__id'))] = {
                    'name': permission.get('permissions__name'),
                    'path': permission.get('permissions__path'),
                    'weight': permission.get('permissions__weight'),
                    'children': []
                }
            permission_list.append(permission.get('permissions__path'))
        return {
            'permissions': permissions,
            'permission_menu': permission_menu_dict,
            'permission_list': permission_list
        }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我辈李想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值