zoukankan      html  css  js  c++  java
  • django-权限管理(day89)

    创建权限表

    基于角色的权限管理,一个员工可以有多个角色,每个角色的访问权限以url的方式存储。
    基于角色的权限管理

    建表

    from django.db import models
    
    
    class User(models.Model):
        """
        用户表
        """
        username = models.CharField(verbose_name='用户名', max_length=32)
        password = models.CharField(verbose_name='密码', max_length=64)
        email = models.EmailField(verbose_name='邮箱')
    
        def __str__(self):
            return self.username
    
    
    class Role(models.Model):
        """
        角色表
        """
        caption = models.CharField(verbose_name='角色', max_length=32)
    
        def __str__(self):
            return self.caption
    
    
    class User2Role(models.Model):
        """
        用户角色关系表
        """
        user = models.ForeignKey(User, verbose_name='用户', related_name='roles')
        role = models.ForeignKey(Role, verbose_name='角色', related_name='users')
    
        def __str__(self):
            return '%s-%s' % (self.user.username, self.role.caption,)
    
    
    class Menu(models.Model):
        """
        菜单表
        """
        caption = models.CharField(verbose_name='菜单名称', max_length=32)
        parent = models.ForeignKey('self', verbose_name='父菜单', related_name='p', null=True, blank=True)
    
        def __str__(self):
            prev = ""
            parent = self.parent
            while True:
                if parent:
                    prev = prev + '-' + str(parent.caption)
                    parent = parent.parent
                else:
                    break
            return '%s-%s' % (prev, self.caption,)
    
    
    class Permission(models.Model):
        """
        权限
        """
        caption = models.CharField(verbose_name='权限', max_length=32)
        url = models.CharField(verbose_name='URL正则', max_length=128)
        menu = models.ForeignKey(Menu, verbose_name='所属菜单', related_name='permissions',null=True,blank=True)
    
        def __str__(self):
            return "%s-%s" % (self.caption, self.url,)
    
    
    class Action(models.Model):
        """
        操作:增删改查
        """
        caption = models.CharField(verbose_name='操作标题', max_length=32)
        code = models.CharField(verbose_name='方法', max_length=32)
    
        def __str__(self):
            return self.caption
    
    
    class Permission2Action2Role(models.Model):
        """
        权限操作关系表
        """
        permission = models.ForeignKey(Permission, verbose_name='权限URL', related_name='actions')
        action = models.ForeignKey(Action, verbose_name='操作', related_name='permissions')
        role = models.ForeignKey(Role, verbose_name='角色', related_name='p2as')
    
        class Meta:
            unique_together = (
                ('permission', 'action', 'role'),
            )
    
        def __str__(self):
            return "%s-%s-%s" % (self.permission, self.action, self.role,)
    

    models查询权限

    def permit(request):
        """
        权限管理,获取权限,并存放在session中
        :param request:
        :return:
        """
        from django.db.models import Count
    
        user_obj = models.User.objects.filter(username="zouruncheng").first()
        print(user_obj)
    
        # 获取 user2role信息
        x = models.User2Role.objects.filter(user_id=user_obj.id)
    
    
        # 通过users关联到User2Role表,通过user__关联到user表。获取当前用户的角色
        role_obj = models.Role.objects.filter(users__user__username="zouruncheng").all()
        print(role_obj)
    
        # 一个用户可能有多个角色,查询出的数据可能重复。annotate分组问题?
        # permission_list = models.Permission2Action2Role.objects.filter(role__in=role_obj).
        #     values("permission__url","action__code").annotate(c=Count("id"))
    
        # 使用distinct时效率较低,不会增加额外的列
        permission_list = models.Permission2Action2Role.objects.filter(role__in=role_obj).
            values("permission__url","action__code").distinct()
    
        print(permission_list)
    
        # 构造权限条件
        permission_dict = {}
        for item in permission_list:
            if item["permission__url"] in permission_dict:
                permission_dict[item["permission__url"]].append(item["action__code"])
            else:
                permission_dict[item["permission__url"]]=[item["action__code"]]
        print(permission_dict)
        # {'/order.html': ['post', 'get', 'edit', 'del'], '/users.html': ['post', 'get', 'edit', 'del']}
    
        request.session["permission_dict"] = permission_dict
        return HttpResponse("模拟登录成功")
    

    模拟权限访问

    1.建立一个关于权限访问的中间件
    MIDDLEWARE = [
        'middleware.permission.PermissionMiddle',
    ]
    

    2.中间件

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    
    class PermissionMiddle(MiddlewareMixin):
        """
        权限过滤,中间件
        """
        def process_request(self,request,*args,**kwargs):
    
            # 只有授权才能访问的url
            invalid_url = ["/permit/order.html"]
    
            if request.path_info in invalid_url:
                action = request.GET.get("md")  # GET传参---?md=get
                permission_dic = request.session.get("permission_dict")
                # {
                #   '/order.html': ['post', 'get', 'edit', 'del'],
                #   '/users.html': ['post', 'get', 'edit', 'del']
                # }
                if not permission_dic:
                    return HttpResponse("无权限(未登录)")
    
                action_list = permission_dic.get(request.path_info)
                if not action_list:
                    return HttpResponse("无权限2")
    
                if action not in action_list:
                    return HttpResponse("无权限3")
    

    生成权限菜单

    # ==========================day90===============================================
    # 根据表结构,生成权限菜单
    def menu(request):
        all_menu_list = models.Menu.objects.values("id", "caption", "parent_id")
        # print(all_menu_list)
    
        # user = models.User.objects.filter(rusername="zouruncheng")
        role_list = models.Role.objects.filter(users__user__username="zouruncheng").all()
        permission_list = models.Permission2Action2Role.objects.filter(role__in=role_list).
            values("permission__id", "permission__url", "permission__caption", "permission__menu__id").distinct()
        # print(permission_list)
        # print(permission_list.count())
    
        # 将权限挂靠到菜单上
        all_menu_dict = {}
        for row in all_menu_list:
            row["child"] = []
            row["status"] = False  # 是否显示该权限
            row["opened"] = False  # 菜单是否展开
            all_menu_dict[row["id"]]=row
    
        for per in permission_list:
            if not per["permission__menu__id"]:
                continue
    
            item = {
                "id":per["permission__id"],
                "caption":per["permission__caption"],
                "url":per["permission__url"],
                "parent_id":per["permission__menu__id"],
                "status":True,
                "opened":False
            }
    
            # if re.match("permission__url",request.path_info):
            if re.match(item["url"], "/permit/users.html"):
                item["opened"]=True
    
            pid = item["parent_id"]
    
            all_menu_dict[pid]["child"].append(item)
    
            # 将当前权限的父级status=True
            temp = pid
            while not all_menu_dict[temp]["status"]:
                all_menu_dict[temp]["status"]=True
                temp = all_menu_dict[temp]["parent_id"]
                if not temp:
                    break
    
            # 将当前权限的父级opened = True
            if item["opened"]:
                temp1 = pid
                while not all_menu_dict[temp1]["opened"]:
                    all_menu_dict[temp1]["opened"] = True
                    temp1 = all_menu_dict[temp1]["parent_id"]
                    if not temp1:
                        break
    
        # print(all_menu_dict)
        # print(all_menu_list)
        # 构造菜单和菜单之间的等级关系
        result=[]
        for row in all_menu_list:
            if row["parent_id"]:
                all_menu_dict[row["parent_id"]]["child"].append(row)
            else:
                result.append(row)
        # print(result)
    
        # for row in result:
        #     print("----",row["caption"],row["status"],row["opened"])
            """
            ---- 用户管理 True
            ---- 订单管理 True
            ---- 博客管理 False
            """
            '''
            结构化处理结果
            result= [
                {'id':1, 'caption':'菜单1', parent_id:None,status:True,opened:True,child:[
    
                        {'url':'/order.html','caption': '订单管理','id': 1,'opened': True, 'status': True},
                        {'id':4, 'caption':'菜单1-1', parent_id:1,status:False,opened:False,child:[]},]},
    
                {'id':2, 'caption':'菜单2', parent_id:None,status:True,opened:False,child:[]},
    
                {'id':3, 'caption':'菜单3', parent_id:None,status:False,opened:False,child:[]},
    
            ]
            '''
        def menu_tree(menu_list):
            tpl1 = """
            <div class='menu-item'>
                <div class='menu-header'>{0}</div>
                <div class='menu-body {2}'>{1}</div>
            </div>
            """
            tpl2 = """
            <a href='{0}' class='{1}'>{2}</a>
            """
    
            menu_str = ""
            for menu in menu_list:
                if not menu['status']:
                    continue
                # menu: 菜单,权限(url)
                if menu.get('url'):
                    # 权限
                    menu_str += tpl2.format(menu['url'],'active' if menu['opened'] else "",menu['caption'])
                else:
                    # 菜单
                    if menu['child']:
                        child_html = menu_tree(menu['child'])
                    else:
                        child_html = ""
                    menu_str += tpl1.format(menu['caption'], child_html,"" if menu['opened'] else 'hide')
    
            return menu_str
    
        menu_html = menu_tree(result)
        print(menu_html)
        return render(request,"ShowMenu.html",{"menu_html":menu_html})
    

    前端

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>权限显示菜单</title>
        <style>
            .hide {
                display: none;
            }
    
            .menu-body {
                margin-left: 20px;
            }
    
            .menu-body a {
                display: block;
            }
    
            .menu-body a.active {
                color: red;
            }
        </style>
    
    </head>
    <body>
    {{ menu_html|safe }}
    </body>
    <script src="/static/plugin/jquery-3.2.1.js"></script>
    <script>
        $(function () {
    
            $('.menu-header').click(function () {
                $(this).next().removeClass('hide').parent().siblings().find('.menu-body').addClass('hide');
    
            })
    
        })
    </script>
    </html>
    
  • 相关阅读:
    JAVA BigDecimal 小数点处理
    对 Element UI table中数据进行二次处理
    Kettle-User Defined Java Class使用-大写转换
    多线程-同步函数
    多线程-银行分批存款
    多线程-并发卖票
    多线程-控制两个线程交替打印
    ztree-可拖拽可编辑的树
    ztree-编辑节点(树节点添加,删除,修改)
    ztree-拖拽(排序树)
  • 原文地址:https://www.cnblogs.com/zouruncheng/p/7214131.html
Copyright © 2011-2022 走看看