• 权限组件(5):权限粒度控制到按钮


    效果图:

     一、models层给权限增加url的别名

    这是做是为了在模板用别名判断当前用户是否有这个url(权限)
    rbac/models.py

    class Permission(models.Model):
        """
        权限表
        """
        title = models.CharField(verbose_name='标题', max_length=32)
        url = models.CharField(verbose_name='含正则的URL', max_length=128)
    
        menu = models.ForeignKey(verbose_name='所属菜单', to=Menu, null=True, blank=True,
                                 help_text='null表示不是菜单,非null表示是二级菜单', on_delete=models.CASCADE
                                 )
    
        name = models.CharField(verbose_name='url的别名', max_length=32, unique=True)  # +
    
        pid = models.ForeignKey(verbose_name='关联的权限', to='Permission', null=True, blank=True, related_name='parents',
                                help_text='对于非菜单权限需要选择一个可以成为菜单的权限,用于做默认展开和选中菜单',
                                on_delete=models.CASCADE
                                )
    
        def __str__(self):
            return self.title

    注意:刚创建的时候设置成null=True和blank=True,当添加完数据后再设置unique=True,并删除null=True和blank=True

    二、在初始化权限中增加别名

    把用户权限以字典的形式储存,别名作为key。values还是一个字典,储存其他信息。
    rbac/service/init_permission.py

    from permission_learn import settings
    
    
    def init_permission(current_user, request):
        """
        用户权限的初始化
        :param current_user:  当前登录用户
        :param request:
        :return:
        """
    
        permission_menu_queryset = current_user.roles.filter(permissions__isnull=False).values(
            'permissions__id',
            'permissions__title',
            'permissions__url',
            'permissions__name',
            'permissions__pid_id',
            'permissions__pid__title',  # +
            'permissions__pid__url',
            'permissions__menu_id',
            'permissions__menu__title',
            'permissions__menu__icon',
        )
    
        permission_dict = {}  # + 
    
        menu_dict = {}
    
        for item in permission_menu_queryset:
            permission_dict[item['permissions__name']] = {
                'id': item['permissions__id'],
                'title': item['permissions__title'],
                'url': item['permissions__url'],
                'pid': item['permissions__pid_id'],
                'p_title': item['permissions__pid__title'],
                'p_url': item['permissions__pid__url'],
            }
    
            menu_id = item['permissions__menu_id']
    
            if not menu_id:
                continue
    
            second_menu = {'id': item["permissions__id"], 'title': item['permissions__title'],
                           'url': item['permissions__url']}
    
            if menu_id in menu_dict:
                menu_dict[menu_id]['second_menu'].append(second_menu)
            else:
                menu_dict[menu_id] = {
                    'title': item['permissions__menu__title'],
                    'icon': item['permissions__menu__icon'],
                    'second_menu': [second_menu, ]
                }
    
        request.session[settings.PERMISSION_SESSION_KEY] = permission_dict
        request.session[settings.MENU_SESSION_KEY] = menu_dict 

    三、中间件处理

    rbac/middlewares/rbac.py

    没有太大变化,换一下名字就行

    import re
    
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    from permission_learn import settings
    
    
    class RbacMiddleware(MiddlewareMixin):
       def process_request(self, request):
    
           white_list = settings.WHITE_LIST
    
           current_path = request.path
    
           for valid_url in white_list:
               if re.match(valid_url, current_path):
                   return None
    
           permission_dict = request.session.get(settings.PERMISSION_SESSION_KEY)
    
           if not permission_dict:
               return HttpResponse('请先登录 ')
    
           has_permission = False
    
           url_record = [
               {'title': '首页', 'url': '#'}
           ]
           for item in permission_dict.values():
               regex = '^%s$' % item['url']
               if re.match(regex, current_path):
                   has_permission = True
                   request.current_selected_permission = item['pid'] or item['id']
                   if not item['pid']:  # 选中的是二级菜单
                       url_record.extend([
                           {'title': item['title'], 'url': item['url'], 'class': 'active'}
                       ])
                   else:  # 选中的是具体权限
                       url_record.extend([
                           {'title': item['p_title'], 'url': item['p_url']},
                           {'title': item['title'], 'url': item['url'], 'class': 'active'},
                       ])
                   request.breadcrumb = url_record  # 通过request,把储存信息传给用户
                   break
    
           if not has_permission:
               return HttpResponse('未获取权限,请先获取权限')
    
    

    四、模板处理

    在templatestag里判断用户是否有权限(是否有url的别名)
    rbac/templatestag/rbac.py

    @register.filter()
    def has_permission(request, name):
        """判断是否有权限"""
    
        if name in request.session[settings.PERMISSION_SESSION_KEY]:
            return True

    在需要把权限控制到按钮的模板传入request,和url的别名,并进行判断。这里拿用户列表举例
    业务app/templates/customer_list.html

    {% extends 'layout.html' %}
    {% load rbac %}   <!-- 系统会默认找到templatetags的文件下面的rbac模块 -->
    ...
     {% if request|has_permission:'customer_add' %}
        <a class="btn btn-default" href="/customer/add/">
             <i class="fa fa-plus-square" aria-hidden="true"></i> 添加客户
         </a>
    {% endif %}
    
     {% if request|has_permission:'customer_import' %}
        <a class="btn btn-default" href="/customer/import/">
            <i class="fa fa-file-excel-o" aria-hidden="true"></i> 批量导入
        </a>
    {% endif %}
    
    {% if request|has_permission:'customer_edit' or request|has_permission:'customer_del' %}
         <th>选项</th>
    {% endif %}
    
    {% if request|has_permission:'customer_edit' or request|has_permission:'customer_del' %}
        <td>
            {% if request|has_permission:'customer_edit' %}
                <a style="color: #333333;" href="/customer/edit/{{ row.id }}/">
                    <i class="fa fa-edit" aria-hidden="true"></i>
                </a>
            {% endif %}
            {% if request|has_permission:'customer_del' %}
                |
                <a style="color: #d9534f;" href="/customer/del/{{ row.id }}/">
                    <i class="fa fa-trash-o"></i>
                </a>
            {% endif %}
        </td>
    {% endif %}
    ...

     

  • 相关阅读:
    Docker部署Kafka以及Spring Kafka操作
    Docker本地镜像上传到阿里云仓库
    Gitlab-CI +Docker + Docker-Compose构建可持续集成java项目的镜像
    Ubuntu安装Gitlab Runner
    Linux安装java环境和maven
    Gitlab CI/CD任务一直处于pending
    C语言中#undef作用
    关于a[i]++和a[i++]说明
    keil4编译Error: User Command terminated, Exit-Code = 1解决
    在keil中添加stc系列单片机型号(模型)方法
  • 原文地址:https://www.cnblogs.com/lshedward/p/10499771.html
Copyright © 2020-2023  润新知