菜单的动态显示

设计表结构

    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

 

 

转载于:https://www.cnblogs.com/jassin-du/p/8525243.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值