权限管理菜单展示

作者: _Caesar | 来源:发表于2018-04-14 00:02 被阅读142次

    设计菜单管理问题:

    图片.png

    1.如何生成菜菜单
    2.怎么让这些菜单分级显示并且如果当前访问的url权限默认
    展开如果是组内菜单就加粗或者变红
    3.非菜单url,默认选中原菜单。(如果你是点击用户列表进来的
    那么你看到页面了,如果你点击添加的时候,你的那个用户列看不见了
    这就不好了。所以要设计当你点击添加按钮的时候,那个用户列表被默认选中)
    菜单管理

    菜单一:
       用户管理
       权限管理
    菜单二:
       订单管理
       角色管理
    

    分级做了菜单。这些菜单该显示什么菜单?是当前用户登录之后从数据库拿到用户拥有的权限,然后把权限搞成菜单
    在表里面设计了一个组内菜单(自关联),当menu_gp_id为NULL就代表可以作为菜单


    图片.png

    1.在models中添加Menu对象(表)以及和group建立起一对多的关系

    from django.db import models
    
    class Menu(models.Model):
        """
        菜单组
        """
        title = models.CharField(max_length=32)
    
    
    class Group(models.Model):
        """
        权限组
        """
        caption = models.CharField(verbose_name='组名称',max_length=16)
        menu = models.ForeignKey(verbose_name='所属菜单',to='Menu')
    
    
    class Permission(models.Model):
        """
        权限表
        """
        title = models.CharField(verbose_name='标题',max_length=32)
        url = models.CharField(verbose_name="含正则URL",max_length=64)
        is_menu = models.BooleanField(verbose_name="是否是菜单")
        code = models.CharField(verbose_name="代码",max_length=16)
        group = models.ForeignKey(verbose_name='所属组',to="Group")
    
        class Meta:
            verbose_name_plural = "权限表"
    
        def __str__(self):
            return self.title
    
    class User(models.Model):
        """
        用户表
        """
        username = models.CharField(verbose_name='用户名',max_length=32)
        password = models.CharField(verbose_name='密码',max_length=64)
        email = models.CharField(verbose_name='邮箱',max_length=32)
    
        roles = models.ManyToManyField(verbose_name='具有的所有角色',to="Role",blank=True)
    
        class Meta:
            verbose_name_plural = "用户表"
    
        def __str__(self):
            return self.username
    
    class Role(models.Model):
        """
        角色表
        """
        title = models.CharField(max_length=32)
        permissions = models.ManyToManyField(verbose_name='具有的所有权限',to='Permission',blank=True)
        class Meta:
            verbose_name_plural = "角色表"
    
        def __str__(self):
            return self.title
    models
    

    2.初始化获取菜单信息+权限信息

    from django.conf import settings
    
    
    def init_permission(user,request):
        """
        初始化权限信息,获取权限信息并放置到session中。
        :param user:
        :param request:
        :return:
        """
        permission_list = user.roles.values('permissions__title',              # 用户列表
                                            'permissions__url',
                                            'permissions__code',
                                            'permissions__is_menu',            # 是否是菜单
                                            'permissions__group_id',
                                            'permissions__group__menu_id',     # 菜单ID
                                            'permissions__group__menu__title',#  菜单名称
                                            ).distinct()
    
        menu_list = []
        # 去掉不是菜单的URL
        for item in permission_list:
            if not item['permissions__is_menu']:
                continue
            tpl = {
                    'menu_id':item['permissions__group__menu_id'],
                    'menu_title':item['permissions__group__menu__title'],
                    'title':item['permissions__title'],
                    'url':item['permissions__url'],
                    'active':False,
            }
            menu_list.append(tpl)
    
        request.session[settings.PERMISSION_MENU_KEY] = menu_list
    
    
        # 权限相关
        result = {}
        for item in  permission_list:
            group_id = item['permissions__group_id']
            code = item['permissions__code']
            url = item['permissions__url']
            if group_id in result:
                result[group_id]['codes'].append(code)
                result[group_id]['urls'].append(url)
            else:
                result[group_id] = {
                    'codes':[code,],
                    'urls':[url,]
                }
    
        request.session[settings.PERMISSION_URL_DICT_KEY] = result
    
    init_permission.py
    

    结构化数据示例:

    mport re
    menu_list = [
        {'menu_id':1, 'menu_title':'菜单一','title':'用户列表','url':'/userinfo/','active':False},
        {'menu_id':1, 'menu_title':'菜单一','title':'订单列表','url':'/order/','active':False},
        {'menu_id':2, 'menu_title':'菜单二','title':'xxx列表','url':'/xxx/','active':False},
        {'menu_id':2, 'menu_title':'菜单二','title':'iii列表','url':'/uuu/','active':False},
    ]
    
    current_url = "/userinfo/"
    
    res={}
    
    for tem in menu_list:
        mid=tem["menu_id"]
        mtitle=tem["menu_title"]
        title=tem["title"]
        url=tem["url"]
        active=False
        if re.match(url,current_url):
            active=True
        if mid in res:
            res[mid]["children"].append({"title":title,"url":url,"active":active})
            if active:
                res[mid]["active"]=True
        else:
    
            res[mid]={
                "menu_id":mid,
                "menu_title":mtitle,
                "active":active,
                "children":[
                    {"title":title,"url":url,"active":True},
    
                ]
            }
    
    print(res)
    

    结果:

    aa={
        1:
            {
                'menu_id': 1,
                'menu_title': '菜单一',
                'active': True,
                'children': [{'title': '用户列表', 'url': '/userinfo/', 'active': True},
                             {'title': '订单列表', 'url': '/order/', 'active': True}]
            },
        2:
            {
            'menu_id': 2,
            'menu_title': '菜单二',
            'active': True,
            'children': [{'title': 'xxx列表', 'url': '/xxx/', 'active': True},
                         {'title': 'iii列表', 'url': '/uuu/', 'active': True}]
           }
    }
    

    3.显示多级菜单

    模块中操作
    其中菜单部分由自定义标签生产
    具体展示页面则用模块继承:如userinfo

    a.base.html

    {% load rbac %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/rbac/rbac.css">
    </head>
    <body>
    <div style="float: left;width: 20%;height: 900px;background-color: darkgrey">
      {% menu_html request %}
    </div>
    <div style="float: left;width: 80%">
       {% block content %}
        {% endblock %}
    </div>
    </body>
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/rbac/rbac.js"></script>
    </html>
    

    b.userinfo.html

    {%  extends "base.html" %}
    {% block content %}
    {%   if pagepermission.has_add %}
    <p><a href="">添加</a></p>
    {% endif %}
    <table>
        <thead>
        <th>id</th>
        <th>name</th>
        <th>操作</th>
        </thead>
    
        <tbody>
        {% for foo in data_list %}
          <tr>
          <td>{{ foo.id }}</td>
          <td>{{ foo.name }}</td>
          <td>
            {% if pagepermission.has_edit %}
                <a href="#">编辑</a>
            {% endif %}
    
          {% if pagepermission.has_del %}
              <a href="#">删除</a>
          {% endif %}
          </td>
          </tr>
        {% endfor %}
    
    {% endblock %}
    

    c.建立自定义标签

    rbac/templatetags/rbac.py

    import re
    from django.template import Library
    from django.conf import settings
    register = Library()
    
    @register.inclusion_tag("menuList.html")
    def menu_html(request):
        menu_list = request.session[settings.PERMISSION_MENU_KEY]
        current_url = request.path_info
        result = {}
        for item in menu_list:
            url = item['url']
            regex = "^{0}$".format(url)
            active = False
            if re.match(regex,current_url):
                active = True
    
            menu_id = item['menu_id']
            if menu_id in result:
                result[menu_id]['children'].append({'title': item['title'], 'url': item['url'], 'active': active})
                if active:
                    result[menu_id]['active'] = True
            else:
                result[menu_id] = {
                    'menu_id': menu_id,
                    'menu_title': item['menu_title'],
                    'active': active,
                    'children': [
                        {'title': item['title'], 'url': item['url'], 'active': active},
                    ]
                }
    
        return {'menu_dict':result}
    
    rbac.py
    
    

    d.menulist.html

    {% for k,item in menu_dict.items %}
     <div class="item">
           <div class="item_title">{{ item.menu_title }}</div>
           {% if item.active %}
            <div class="item_permissions">
               {% else %}
               <div class="item_permissions hide">
           {% endif %}
              {% for v in item.children %}
               {% if v.active %}
                   <a href="#" class="active">{{ v.title }}</a>
                   {% else %}
                   <a href="#">{{ v.title }}</a>
               {% endif %}
              {% endfor %}
           </div>
       </div>
    {% endfor %}
    
    

    e.css和js

    在rbac建立static/rbac目录在其中创建rbac.css和rbac.js

    .item_permissions{
        padding: 3px 10px;
    }
    
    .item_permissions a{
        display: block;
    }
    
    .item_permissions a.active{
        color: red;
    }
    
    .hide{
        display: none;
    }
    
    rbac.css
    
    

    ···
    $(function () {
    $(".item_title").click(function () {
    $(this).next().toggleClass("hide")
    });
    })
    ···

    .四.菜单展示的改进

    因为当我们对用户部分进行增删改查的时,用户列表也应该展开的,但是我们上面所写的当我们点击增加删除编辑按钮时,用户菜单会闭合而不是展开的对此我们要进行一些改进

    1.在权限表中增加字段menu_gp,并删除is_menu字段

    from django.db import models
    
    class Menu(models.Model):
        '''
        菜单表
        '''
        title=models.CharField(max_length=32,verbose_name="菜单名称")
    
    class Group(models.Model):
        '''
        权限组
        '''
        caption=models.CharField(max_length=32,verbose_name="组名称")
        menu=models.ForeignKey(verbose_name="所属菜单",to="Menu",default=1)
    
    class Permission(models.Model):
        """
        权限表
        """
        title = models.CharField(verbose_name='标题',max_length=32)
        url = models.CharField(verbose_name="含正则URL",max_length=64)
        # is_menu = models.BooleanField(verbose_name="是否是菜单")
        menu_gp=models.ForeignKey(verbose_name="组内菜单",to="Permission",null=True,blank=True)
        code=models.CharField(max_length=32,verbose_name="代码",default="list")
        group=models.ForeignKey(verbose_name="s所在权限组",to="Group",default=1)
    
    
        class Meta:
            verbose_name_plural = "权限表"
    
        def __str__(self):
            return self.title
    
    class User(models.Model):
        """
        用户表
        """
        username = models.CharField(verbose_name='用户名',max_length=32)
        password = models.CharField(verbose_name='密码',max_length=64)
        email = models.CharField(verbose_name='邮箱',max_length=32)
    
        roles = models.ManyToManyField(verbose_name='具有的所有角色',to="Role",blank=True)
    
        class Meta:
            verbose_name_plural = "用户表"
    
        def __str__(self):
            return self.username
    
    class Role(models.Model):
        """
        角色表
        """
        title = models.CharField(max_length=32)
        permissions = models.ManyToManyField(verbose_name='具有的所有权限',to='Permission',blank=True)
        class Meta:
            verbose_name_plural = "角色表"
    
        def __str__(self):
            return self.title
    
    moedels.py
    

    2.修改初始化中菜单

    init_permission.py

    from django.conf import settings
    def init_permission(user,request):
        """
        初始化权限信息,获取权限信息并放置到session中。
        :param user:
        :param request:
        :return:
        """
        permission_list = user.roles.values('permissions__title',
                                            "permissions__code",
                                            "permissions__id",
                                            'permissions__url',
                                            'permissions__menu_gp_id',
                                            "permissions__group__id",
                                            "permissions__group__menu_id",
                                            "permissions__group__menu__title",
                                            ).distinct()
    
    
    
        menu_list=[]
        for item in permission_list:
            tpl={
                "id":item["permissions__id"],
                "title":item["permissions__title"],
                "menu_title":item["permissions__group__menu__title"],
                "url":item["permissions__url"],
                "menu_id":item["permissions__group__menu_id"],
                "menu_gp_id":item["permissions__menu_gp_id"],
            }
            menu_list.append(tpl)
    
        request.session[settings.PERMISSIONS_MENU_KEY]=menu_list
    
    
    
        # menu_list=[]
        # for item in permission_list:
        #     if not item["permissions__is_menu"]:
        #         continue
        #
        #     tpl={
        #         "menu_id":item["permissions__group__menu_id"],
        #         "menu_title":item["permissions__group__menu__title"],
        #         "title":item["permissions__title"],
        #         "url":item["permissions__url"],
        #         "active":False,
        #     }
        #
        #     menu_list.append(tpl)
        # print(menu_list)
        # request.session[settings.PERMISSIONS_MENU_KEY]=menu_list
         #权限管理
        result={}
        for item in permission_list:
            groupid=item["permissions__group__id"]
            code=item["permissions__code"]
            url=item["permissions__url"]
    
            if groupid in result:
                result[groupid]["codes"].append(code)
                result[groupid]["urls"].append(url)
            else:
                result[groupid]={
                    "codes":[code,],
                    "urls":[url,]
                }
    
    
        print(result)
    
    
        request.session[settings.PERMISSIONS_URL_DICT_KEY] = result
    
    init_permission.py
    

    3.修改定义标签

    rbac.py

    import  re
    from django.conf import settings
    from django.template import Library
    register = Library()
    @register.inclusion_tag("menuList.html")
    def menu_html(request):
        menu_list=request.session.get(settings.PERMISSIONS_MENU_KEY)
        currenturl=request.path_info
    
    
        menu_dict={}
        for item in menu_list:
            if not item["menu_gp_id"]:
                menu_dict[item["id"]]=item
        for item in menu_list:
            regex="^{0}$".format(item["url"])
            if re.match(regex,currenturl):
                menu_gp_id=item["menu_gp_id"]
                if not menu_gp_id:
                    menu_dict[item["id"]]["active"]=True
                else:
                    menu_dict[item["menu_gp_id"]]["active"]=True
        '''
        menu_dict={
        1: {'id': 1, 'title': '用户列表', 'url': '/userinfo/', 'menu_gp_id': None, 'menu_id': 1, 'menu_title': '菜单管理', 'active': True},
        5: {'id': 5, 'title': '订单列表', 'url': '/order/', 'menu_gp_id': None, 'menu_id': 2, 'menu_title': '菜单2'}}
        '''
        print(menu_dict,"11111111111111111111111111111111111111111111")
        result = {}
        for item in menu_dict.values():
            menu_id=item["menu_id"]
            menu_title=item["menu_title"]
            active=item.get("active")
            url=item["url"]
            title=item["title"]
    
            if menu_id in result:
                result[menu_id]["children"].append({"title":title,"url":url,"active":active})
                if active:
                    result[menu_id]["active"]=True
            else:
                result[menu_id]={
                    "menu_id":menu_id,
                    "menu_title":menu_title,
                    "active":active,
                    "children":[
                        {"title":title,"url":url,"active":active},
                    ]
    
                }
    
        print(result)
    
        # for item in menu_list:
        #     menu_id=item["menu_id"]
        #     menu_title=item["menu_title"]
        #     title=item["title"]
        #     url=item["url"]
        #     active=False
        #     regex="^{0}$".format(url)
        #     if re.match(regex,currenturl):
        #         active=True
        #
        #     if menu_id in result:
        #         result[menu_id]["children"].append({{"title":title,"url":url,"active":active},})
        #         if active:
        #             result[menu_id]["active"]=active
        #     else:
        #         result[menu_id]={
        #             "menu_id":menu_id,
        #             "menu_title":menu_title,
        #             "active":active,
        #             "children":[
        #                 {"title":title,"url":url,"active":active},
        #             ]
        #         }
        # print(result)
        return {"menu_dict":result}
    
    rbac.py
    

    其他不做修改

    相关文章

      网友评论

      本文标题:权限管理菜单展示

      本文链接:https://www.haomeiwen.com/subject/aqizhftx.html