• Django


    一、非菜单权限对应的一级菜单展开

      需求:客户列表和账单列表页面中都有添加按钮,当点击添加客户(或编辑客户、删除客户)时,客户列表所属的一级菜单展开,当点击添加账单(或编辑账单、删除账单)时,账单列表所属的一级菜单展开。

    1、permission表新增一个pid字段,表示非菜单权限的父级菜单权限id,permission模型类如下:

    class Permission(models.Model):
        """
        权限表
        """
        url = models.CharField(verbose_name='含正则的URL', max_length=32)
        title = models.CharField(verbose_name='标题', max_length=32)
        menu = models.ForeignKey(verbose_name='标题', to="Menu", on_delete=models.CASCADE, null=True)
        name = models.CharField(verbose_name='url别名', max_length=32, default="")
        pid = models.ForeignKey("self", on_delete=models.CASCADE, null=True, verbose_name='父权限')
    
        def __str__(self):
            return self.title

    2、修改权限列表数据结构,注入session,setsession.py中代码如下:

    def initial_session(user_obj, request):
        """
        将当前登录人的所有权限url列表和
        自己构建的所有菜单权限字典和
        权限表name字段列表注入session
        :param user_obj: 当前登录用户对象
        :param request: 请求对象HttpRequest
        """
        # 查询当前登录人的所有权限列表
        ret = Role.objects.filter(user=user_obj).values('permissions__url',
                                                        'permissions__title',
                                                        'permissions__name',
                                                        'permissions__pk',
                                                        'permissions__pid',
                                                'permissions__menu__title',
                                                    'permissions__menu__icon',
                                                    'permissions__menu__id').distinct()
        permission_list = []
        permission_names = []
        permission_menu_dict = {}
        for item in ret:
            # 获取用户权限列表用于中间件中权限校验,改变数据结构
            permission_list.append({
                'url':item['permissions__url'],
                'id':item['permissions__pk'],
                'pid':item['permissions__pid'],
                'title':item['permissions__title']
            })
            # 获取权限表name字段用于动态显示权限按钮
            permission_names.append(item['permissions__name'])
    
            menu_pk = item['permissions__menu__id']
            if menu_pk:
                if menu_pk not in permission_menu_dict:
                    permission_menu_dict[menu_pk] = {
                        "menu_title": item["permissions__menu__title"],
                        "menu_icon": item["permissions__menu__icon"],
                        "children": [
                            {
                                "title": item["permissions__title"],
                                "url": item["permissions__url"],
                     "pk": item["permissions__pk"]
                            }
                        ],
                    }
                else:
                    permission_menu_dict[menu_pk]["children"].append({
                        "title": item["permissions__title"],
                        "url": item["permissions__url"],
                    })
        print('权限列表', permission_list)
        print('菜单权限', permission_menu_dict)
        # 将当前登录人的权限列表注入session中
        request.session['permission_list'] = permission_list
        # 将权限表name字段列表注入session中
        request.session['permission_names'] = permission_names
        # 将当前登录人的菜单权限字典注入session中
        request.session['permission_menu_dict'] = permission_menu_dict

    3、因修改了权限列表的数据结构,所以中间件校验权限也需要修改,中间件middlewares.py代码如下:

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import redirect, HttpResponse
    import re
    class PermissionMiddleWare(MiddlewareMixin):
        def process_request(self, request):
            # 设置白名单放行
            for reg in ["/login/", "/admin/*"]:
                ret = re.search(reg, request.path)
                if ret:
                    return None
    
            # 检验是否登录
            user_id = request.session.get('user_id')
            if not user_id:
                return redirect('/login/')
    
            # 检验权限
            permission_list = request.session.get('permission_list')
            for item in permission_list:
                reg = '^%s$' % item["url"]
                ret = re.search(reg, request.path)
                if ret:
                    show_id = item["pid"] or item["id"]
                    request.show_id = show_id  # 给request对象添加一个属性
                    return None
            return HttpResponse('无权访问')

    4、修改my_tags.py文件,代码如下:

    @register.inclusion_tag("menu.html")
    def get_menu_styles(request):
        permission_menu_dict = request.session.get("permission_menu_dict")
        print("permission_menu_dict", permission_menu_dict)
    
        for val in permission_menu_dict.values():
            for item in val["children"]:
                val["class"] = "hide"
                # /customer/
                # /customer/edit/3
                if request.show_id == item["pk"]:
                    val["class"] = ""
    
        return {"permission_menu_dict": permission_menu_dict}

    总结:之前菜单权限和非菜单权限之间没有关系,通过在权限表中添加pid字段,建立菜单权限和非菜单权限之间的关系,来控制访问某一非菜单权限时,其对应的菜单权限展开。

    二、面包屑导航

      需求:实现面包屑导航

    1、修改中间件,middlewares.py中代码如下:

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import redirect, HttpResponse
    import re
    class PermissionMiddleWare(MiddlewareMixin):
        def process_request(self, request):
            # 设置白名单放行
            for reg in ["/login/", "/admin/*"]:
                ret = re.search(reg, request.path)
                if ret:
                    return None
    
            # 检验是否登录
            user_id = request.session.get('user_id')
            if not user_id:
                return redirect('/login/')
    
            # 检验权限
            permission_list = request.session.get('permission_list')
    
            # 路径导航列表
            request.breadcrumb = [
                {
                    "title": "首页",
                    "url": "/"
                },
            ]
            for item in permission_list:
                reg = '^%s$' % item["url"]
                ret = re.search(reg, request.path)
                if ret:
                    show_id = item["pid"] or item["id"]
                    request.show_id = show_id  # 给request对象添加一个属性
    
                    # 确定面包屑列表
                    if item["pid"]:
                        ppermission = Permission.objects.filter(pk=item["pid"])
                                              .first()
                        request.breadcrumb.extend(
                            [{  # 父权限字典
                                "title": ppermission.title,
                                "url": ppermission.url
                            },
                            {  # 子权限字典
                                "title": item["title"],
                                "url": request.path
                            }]
                        )
                    else:
                        request.breadcrumb.append(
                            {
                                "title": item["title"],
                                "url": item["url"]
                            }
                        )
                        
                    return None
    
            return HttpResponse('无权访问')

    2、公共模板页面base.html中面包屑导航位置的代码如下:

    <div>
        <ol class="breadcrumb no-radius no-margin">
           {% for item in request.breadcrumb %}
               <li><a href="{{ item.url }}">{{ item.title }}</a></li>
           {% endfor %}
        </ol>
    </div>
  • 相关阅读:
    Spring Cloud Alibaba(一)为什么选用Spring Cloud Alibaba?
    Spring Cloud Alibaba(三)Nacos配置中心
    配置JNDI数据源
    vue动态表单DynamicForm 吴小明
    css变量的声明和读取 吴小明
    【图片预览】第二种方式:hooks子组件调用父组件方法 吴小明
    react+antd快捷菜单搜索组件:MenuSearch 吴小明
    【图片预览】第一种方式:hooks父组件调用子组件方法(1、子组件中使用useImperativeHandle钩子 2、父组件中使用useRef)【reactviewer】 吴小明
    ios遮罩层滚动穿透问题 吴小明
    【图片预览】第三种方式:将组件数据放在公共状态下 吴小明
  • 原文地址:https://www.cnblogs.com/li-li/p/9979048.html
Copyright © 2020-2023  润新知