• 菜单的动态显示


    设计表结构

        models中创建类:五个类,七张表
        角色表:
        用户表:
        权限表:

        权限组表:

        菜单表: 

        角色表和权限表是多对多的关系(一个角色可以有多个权限,一个权限可以对应多个角色)
        用户表和角色表是多对多的关系(一个用户可以有多个角色,一个角色有多个用户)

        所以有会多生成两张关系表

        一个菜单下面有多个组

        一个组下面有多个菜单

        一个菜单下面有多个权限

    /users/
    /users/add    
    /users/
    /users/add
    
    
    展示方式:
    
        /users/
    
        用户管理
           
           <a href='/users/'>查看用户</a>
           <a href='/users/add'>添加用户</a>
         
        订单管理
           <a href='/orders/'>查看订单</a>
           <a href='/orders/add'>添加订单</a>
    对于菜单的展示要求:
        用户访问的url:/users/
        
        1 /users/所在的菜单展开,其它菜单收起来
        
        2 /users/权限对应的a标签加active样式
     想要的数据格式样式
      menu_dict={
         1:{
            "title":"菜单一",
            "active":True,
            "children":[
                 {"title":"添加用户","url":"xxxxxxxxxxx","active":False},
                 {"title":"查看用户","url":"xxxxxxxxxxx","active":True},
            
            ]},
        2:{
            "title":"菜单二",
            "active":False,
            "children":[
                  {"title":"添加用户","url":"xxxxxxxxxxx","active":False},
                  {"title":"查看用户","url":"xxxxxxxxxxx","active":False},
            
            ]    
     
      }
       
    # 修改表结构
    
    问题一:
    需求:每一个组代表一张表,以permissionGruop为一级菜单,会导致一级菜单过多,展示效果不理想
    每个一级菜单最多只有2个二级菜单(对应的权限太少)
    解决: 给permissionGroup组再分组menu
        
    class Menu(一级菜单)
           id caption  
           
    1  用户角色管理
      将角色组和用户组融合在一起

    显示的样式

     为什么菜单栏不显示删除及编辑用户(含有正则)?

    在页面无法给(d+)传数据

    需求2:
        注意:含正则表达式的权限不能放在菜单栏
        解决办法:  
        在同一组中,将不会放入菜单栏中的权限归属到放到菜单栏中的权限 is_menu parent
    1 查看用户列表 /users/ 用户组 list True null 2 添加用户 /users/add/ 用户组 add False 1 3 删除用户 /users/delete/(d+) 用户组 delete False 1 4 编辑用户 /users/edit/(d+) 用户组 edit False 1 5 查看订单列表 /orders/ 订单组 list True null 6 添加订单 /orders/add/ 订单组 add False 5 7 删除订单权限 /orders/delete/(d+) 订单组 delete False 5 8 编辑订单 /orders/edit/(d+) 订单组 edit False 5

    对于权限表的某一个组中,对于加入菜单栏中的权限记录,让字段parent为null,如果不的话,parent归属到该组中加入菜单栏的权限中

    所以在permission加一个自关联字段

    # 关于字段parent 1的意思:归属到自关联字段users,菜单栏没有我,但要有我的归属

    # 权限显示,但要只知道哪一个权限要标红
    例如:
        # [{'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1},
        #  {'id': 2, 'url': '/users/add/', 'title': '添加用户', 'pid': 1, 'menu_name': '用户角色管理', 'menu_id': 1},
        # {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}]
    
    
    关于pid的作用
    但为none就要显示在菜单栏中
    关于设计菜单管理-----问题:
    1、如何生成菜单 2、怎么让这些菜单分级显示并且如果当前访问的url权限默认展开如果是组内菜单就加粗或者变红 3、非菜单url,默认选中原菜单。(如果你是点击用户列表进来的,那么你看到页面了,如果你点击添加的时候,你的那个用户列看不见了,这就不好了。
    所以要设计当你点击添加按钮的时候,那个用户列表被默认选中) 菜单管理   菜单一     用户管理     权限管理   菜单二     订单管理     角色管理 分级做了菜单。这些菜单该显示什么菜单?是当前用户登录之后从数据库拿到这个用户拥有的权限,然后把权限搞成菜单 在表里面设计了一个组内菜单(自关联 ),当pid为NULL就代表可以作为菜单
    用户访问的路径有2种情况:
        1:不含有正则的url----> 要展示在菜单栏(通过pid是否为None来判断)
        2:含有正则的url----> 不在菜单栏里显示(但要找到它的归属,将展开并高亮)

    怎样获得菜单栏的数据结构及处理

       # 在initial中间件完成
     # 用户的权限信息
        permission_info = user.roles.all().values("permissions__id",
                                                  "permissions__url",
                                                  "permissions__title",
                                                  "permissions__permission_group_id",  # 权限的组
                                                  "permissions__code",  # 权限的编号
                                                  "permissions__parent_id",   # 权限的一级菜单
                                                  "permissions__permission_group__menu__caption",  # 分组的组的名字
                                                  "permissions__permission_group__menu_id",
                                                  ).distinct()
        # print('permission_info',permission_info)
        # permission_info < QuerySet[{'permissions__id': 5,
        #                               'permissions__url': '/orders/',
        #                                'permissions__title': '查看订单列表',
        #                             'permissions__permission_group_id': 3,
        #                               'permissions__code': 'list',
        #                             'permissions__parent_id': None,
        #                                'permissions__permission_group__menu__caption': '订单管理',
        #                             'permissions__permission_group__menu_id': 2}] >
    
    
    
        #  8个键值对太多了,名字太长,下面是用来简化数据
        #  创建生成菜单的数据 ---> 简化上面的数据
        permission_list=[]
        for permission_item in permission_info:
            temp={
                "id":permission_item["permissions__id"],
                "url":permission_item["permissions__url"],
                "title":permission_item["permissions__title"],
                "pid":permission_item["permissions__parent_id"],
                "menu_name":permission_item["permissions__permission_group__menu__caption"],
                "menu_id":permission_item["permissions__permission_group__menu_id"]
            }
            permission_list.append(temp)
        request.session["permission_list"]=permission_list
      

      # 有几个权限就有几个字典
    # print(permission_list) # [{'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}]
       """
        有几个权限就有几个字典
        [{'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1},
         {'id': 2, 'url': '/users/add/', 'title': '添加用户', 'pid': 1, 'menu_name': '用户角色管理', 'menu_id': 1},
        {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}]
        """
    
        # 当pid为none就要显示在菜单栏中,过滤掉pid有值的
        # temp_dict 过滤掉的数据,只放pid为none------> 存储所有放到菜单栏中的权限 ---> 调整active
        
    # 显示在菜单栏的数据
        temp_dict = {}
        for item in permission_list:
            pid = item["pid"]
            if not pid:
                item["active"] = False  # 添加标志状态
                temp_dict[item["id"]] = item  # 可变数据类型
        # print(temp_dict)
        # {1: {'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1, 'active': False},
        #  5: {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2, 'active': False}}
    
    # 当不是在菜单栏处理
        # 取到用户输入的url,path_info是request提供的方法
        current_path = request.path_info
        import re
        for item in permission_list:
            pid = item["pid"]
            url = "^%s$" % item["url"]
            if re.match(url, current_path):
                if pid:  # 有值,设置他的归属(高亮)
                    temp_dict["pid"]["active"] = True
                else:  # 没有,设置自己
                    item["active"] = True
    
    # 此时的item是可能含有带有正则的url,通过pid找到它的归属菜单栏,修改其active的状态
    
    # 当访问的url是要在菜单栏显示的:直接修改自己的active的状态,将其变红
    
    #问题1:
        为什么循环的是permission_list而不是temp_dict?
    temp_dict里面的数据是要显示在菜单栏里的,其url是不包含正则
    而permission_list里面是用户所有权限的url,当访问的url含有正则,且是用户的权限,虽然不显示在菜单栏,但也要修改其归属菜单的active的状态
    
    # 问题2:
       上面的代码在处理active的状态,但最终要处理数据是temp_dict,而不是permission_list?
        因为它们两个都是引用同一个数据类型(permission_list),上面本质也不是改permission_list里面的active而是改temp_dict,它们两个是关联的
    
    
    想要构成的数据格式
        """
        menu_dict = {
            1: {
                "title": "用户角色管理",
                "active": True,
                "children": [
                    {"title": "添加用户", "url": "xxxxxxxxxxx", "active": False},
                    {"title": "查看用户", "url": "xxxxxxxxxxx", "active": True},
    
                ]},
    
            2: {
                "title": "订单管理",
                "active": False,
                "children": [
                    {"title": "添加用户", "url": "xxxxxxxxxxx", "active": False},
                    {"title": "查看用户", "url": "xxxxxxxxxxx", "active": False},
    
                ]
    
            }}
        """
        # 将temp_dict转换为最终想要的格式
        menu_dict = {}
        for item in temp_dict.values():
            if item["menu_id"] in menu_dict:  # 有就添加,没有就创建
                temp = {"title": item["title"], "url": item["url"], "active": item["active"]},
                menu_dict[item["menu_id"]]["children"].append(temp)
    
                if item["active"]:  # 用户的active为True,则将父亲的active改为True
                    menu_dict[item["menu_id"]]["active"] = True
            else:
                menu_dict[item["menu_id"]] = {
                    "title": item["menu_name"],
                    "active": item["active"],
                    "children": [
                        {"title": item["title"], "url": item["url"], "active": item["active"]}
                    ]
                }
     print(menu_dict)
    {2: {'title': '订单管理', 'active': True, 'children': [{'title': '查看订单列表', 'url': '/orders/', 'active': True}]}}
    关于自定义标签
    1、先创建templatetags文件夹
            在里面创建一个模板文件my_tags.py
    
    2、导入模块(register的名字是固定的,不可改变)
        from django import template
        register=template.Library()
    
        @register.simple_tag
      def mul(x,y):
        return x*y

    3、在需要使用的页面导入模板(使用模板)
      {% load my_tags %}

    4:、在调用模板函数
      {% mul 2 4 %}


    关于权限利用到的自定义标签
    1、先创建templatetags文件夹
            在里面创建一个模板文件my_tags.py
    
    
    2、导入模块(register的名字是固定的,不可改变)
        from django import template
        register=template.Library()
    
        @register.inclusion_tag("menu.html")
      def get_menu(request):
          ...
        return {"menu_dict":menu_dict} # 将数据传到menu.html

    3: 创建一个独立显示菜单的页面menu.html
    4: 在base页面调用模板的函数
      {% get_menu request %}
    @register.inclusion_tag("menu.html")
    def get_menu(request):
        # 从session中取出数据
        permission_list = request.session["permission_list"]
        """
        有几个权限就有几个字典
        [{'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1},
         {'id': 2, 'url': '/users/add/', 'title': '添加用户', 'pid': 1, 'menu_name': '用户角色管理', 'menu_id': 1},
        {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}]
        """
    
        # 当pid为none就要显示在菜单栏中,过滤掉pid有值的
        # temp_dict 过滤掉的数据,只放pid为none------> 存储所有放到菜单栏中的权限 ---> 调整active
        temp_dict = {}
        for item in permission_list:
            pid = item["pid"]
            if not pid:
                item["active"] = False  # 添加标志状态
                temp_dict[item["id"]] = item  # 可变数据类型
        # print(temp_dict)
        # {1: {'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1, 'active': False},
        #  5: {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2, 'active': False}}
    
        # 取到用户输入的url,path_info是request提供的方法
        current_path = request.path_info
        import re
        for item in permission_list:
            pid = item["pid"]
            url = "^%s$" % item["url"]
            if re.match(url, current_path):
                if pid:  # 有值,设置他的归属(高亮)
                    temp_dict["pid"]["active"] = True
                else:  # 没有,设置自己
                    item["active"] = True
    
        # 将temp_dict转换为最终想要的格式
        menu_dict = {}
        for item in temp_dict.values():
            if item["menu_id"] in menu_dict:  # 有就添加,没有就创建
                temp = {"title": item["title"], "url": item["url"], "active": item["active"]},
                menu_dict[item["menu_id"]]["children"].append(temp)
    
                if item["active"]:  # 用户的active为True,则将父亲的active改为True
                    menu_dict[item["menu_id"]]["active"] = True
            else:
                menu_dict[item["menu_id"]] = {
                    "title": item["menu_name"],
                    "active": item["active"],
                    "children": [
                        {"title": item["title"], "url": item["url"], "active": item["active"]}
                    ]
                }
        print(menu_dict)
        return {"menu_dict":menu_dict}
    my_tags.py
    {#  封装,在哪里调用都可以使用到左侧菜单内容 #}
    {#这只是样式,布局可能有了#}
        <div class="menu">
    
            {% for item in menu_dict.values %}
    
                <div class="item">
                <div class="title"><a href="">{{ item.title }}</a></div>
                {#            这里少个div ,因为渲染会二选一来操作 #}
                {% if item.active %}
                    <div class="con">
                {% else %}
                    <div class="con hide">
                {% endif %}
            {% for son in item.children %}
                {% if son.active %}
                    <p><a href="{{ son.url }}" class="active">{{ son.title }}</a></p>
                {% else %}
                    <p><a href="{{ son.url }}">{{ son.title }}</a></p>
                {% endif %}
            {% endfor %}
            </div>
    
            </div>
            {% endfor %}
    
            </div>
    
    
    
            <div class="content">
                {% block con %}
    
                {% endblock %}
            </div>
    menu.html

     

  • 相关阅读:
    文件操作
    python中的函数递归和迭代问题
    函数的闭包与装饰器
    函数的名称空间和作用域
    python学习之路(四) ---函数
    python __name__问题
    浅谈python中的引用和拷贝问题
    Python中的缩进问题
    粘包现象
    socket编程
  • 原文地址:https://www.cnblogs.com/jassin-du/p/8525243.html
Copyright © 2020-2023  润新知