二级菜单优化功能

二级菜单的功能优化---渐入佳境

功能1:点击其中之一的一级菜单展示其二级菜单,同时其他一级菜单的二级菜单都处于闭合状态

思路:使用jsDOM操作进行实现

HTML示例代码
<div class="multi-menu">
    {% for menu in menu_list %}
        <div class="item">
            <div class="title"><i class="fa {{ menu.icon }}"></i>
                {{ menu.name }}</div>
            <div class="body">
                {% for child in menu.children %}
                    <a href="{{ child.url }}">{{ child.title }}</a>
                {% endfor %}
                
            </div>
        </div>
    {% endfor %}
</div>

js代码实现

$('.item .title').click(function () {
    $(this).next().removeClass('hide').parent().siblings().find('.body').addClass('hide')
})

//1.先命中一级菜单title,触发点击事件
//2.保证自己没有被隐藏
//3.找到其他body使其隐藏,通过自己先找到父级parent,再找到所有的兄弟siblings的儿子,也就是body,命中后添加hide属性

//如此便实现了这个只显示当前菜单下的二级菜单功能

功能2:访问当前页面,默认选中对应页面展示菜单

思路:在访问的二级菜单url对应a标签中添加 class='active'

1.django中 templatetags文件下使用inclusion_tag进行自定义模板

#从二级菜单的数据结构中获取到需要使用的url,title进行模板渲染
"""
{
    1: {
        'name': '信息管理',
        'icon': 'fa-email',
        'children': [{
            'title': '客户管理',
            'url': '/customer/list/'
        }]
    },
}
"""
from django import template
import re
from permission import settings
register = template.Library()
#自定义模板
@register.inclusion_tag('menu.html')
def menu(request):
    menu_dic = request.session.get(settings.MENU_SESSION_KEY)
    url = request.path_info #获取访问的url

    #获取到url和title进行模板渲染
    for item in menu_dic.values(): #首先循环拿到item表示一级菜单id对应的所有内容

        for i in item['children']: #循环item['children'] 要拿到i 表示二级菜单内的所有内容
            if re.match("^{}$".format(i['url']),url): #将获取到url与session中的url进行正则匹配
                i['class'] = 'active' #匹配成功后给二级菜单字典内添加一组键值对 class='active'
                break
    return {'menu_list':menu_dic.values()}

2.在对应的模板中直接渲染即可,参照功能1中的HTML代码

  <a class="{{ child.class }}" href="{{ child.url }}">{{ child.title }}</a>

根据上面的HTML代码来看,在class=body 下的a标签中添加class='active'进行渲染即可.
***如此便实现了
访问某个页面,默认选中对应页面的展示菜单***
 

功能3访问某个页面,页面对应菜单的二级菜单展示,其他菜单的二级菜单默认关闭

思路:首先先隐藏所有的二级菜单,再根据访问的url展示对应的一级菜单下的二级菜单

#示例代码
from
django import template import re from luffy_permission import settings register = template.Library() #自定义模板 @register.inclusion_tag('menu.html') def menu(request): menu_dic = request.session.get(settings.MENU_SESSION_KEY) url = request.path_info for item in menu_dic.values(): item['class'] = 'hide' #将所有的二级菜单隐藏 for i in item['children']: if re.match("^{}$".format(i['url']),url): i['class'] = 'active' item['class'] = '' #将匹配成功的二级菜单取消隐藏 break return {'menu_list':menu_dic.values()}
<div class="multi-menu">
    {% for menu in menu_list %}
        <div class="item">
            <div class="title"><i class="fa {{ menu.icon }}"></i>
                {{ menu.name }}</div>
            <div class="body {{ menu.class }}">    
                {% for child in menu.children %}
                    <a class="{{ child.class }}" href="{{ child.url }}">{{ child.title }}</a>
                {% endfor %}
                
            </div>
        </div>
    {% endfor %}
</div>

注:先在body中添加class='hide'属性,令所有的二级菜单隐藏,当访问的url页面匹配与session中的url匹配成功后在将 class='' 从而取消隐藏

功能4固定菜单栏展示顺序,因为数据结构是字典(无序的)

思路:将menu表结构改变,添加一个字段weight = model.IntegerField(default=1),导入有序字典(from collections import OrderedDict),根据数值大小进行排序即可

models.py
class
Menu(models.Model): """ 一级菜单 """ name = models.CharField(max_length=30,verbose_name='一级菜单名称') icon = models.CharField(max_length=56, verbose_name='图标', blank=True, null=True) weight = models.IntegerField(default=1) def __str__(self): return self.name #添加一个字段weight
rbac.py
from django import template import re from permission import settings from collections import OrderedDict register = template.Library() #自定义模板 @register.inclusion_tag('menu.html') def menu(request): menu_dic = request.session.get(settings.MENU_SESSION_KEY)
   url = request.path_info order_dic
= OrderedDict() #实例化一个有序字典 for key in sorted(menu_dic,key=lambda n:menu_dic[n]['weight'],reverse=True): order_dic[key] = item = menu_dic[key] #将根据weight字段排序后的menu_dic 赋值给order_dic item['class'] = 'hide' for i in item['children']: if re.match("^{}$".format(i['url']),url): i['class'] = 'active' item['class'] = '' break return {'menu_list':order_dic.values()} #再返回有序字典在模板上顺序渲染

功能5:非菜单权限归属问题 (二级菜单内各种时操作 默认选中并处于显示对应二级菜单)

思路:二级菜单下需要有操作的层级关系,也就是你伪三级菜单 ,更改表结构也就是 权限表(Permission)

 步骤1:表结构设计 models.py

#参照上图所示
class
Permission(models.Model): """ 权限表 menu_id 有的话 表示当前的权限是二级菜单 父权限 没有 是一个普通权限 parent_id 有的话 表示当前就是子权限 没有的话就是一个父权限 """ url = models.CharField(max_length=255,verbose_name='地址') title = models.CharField(max_length=25,verbose_name='标题') menu = models.ForeignKey('Menu',blank=True,null=True) parent = models.ForeignKey('self') #自关联 获取到层级结构

 步骤2:查询和存放在session中的权限信息处理 service/permission.py

 1 from django.conf import settings
 2 
 3 
 4 def init_permission(request,obj):
 5     # 先查到需要的权限信息,
 6 
 7     permission_query = obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url',
 8                                                                                      'permissions__title',
 9                                                                                      'permissions__menu__name',
10                                                                                      'permissions__menu__icon',
11                                                                                      'permissions__menu__id',
12                                                                                      'permissions__menu__weight',
13                                                                                      'permissions__id',
14                                                                                      'permissions__parent_id',
15                                                                                      ).distinct()
16     # 存放权限信息列表
17     permission_list = []
18     # 存放菜单信息的字典
19     menu_dic = {}
20     for item in permission_query:
21         # 将权限信息放到permission_list
22         permission_list.append({'url': item['permissions__url'],
23                                 'pid': item['permissions__parent_id'],
24                                 'id': item['permissions__id'] })
25 
26         #放入菜单信息
27         menu_id = item['permissions__menu__id']
28         if not menu_id:
29             continue
30         if menu_id not in menu_dic:
31             menu_dic[menu_id] = {
32                 'name': item['permissions__menu__name'],
33                 'icon': item['permissions__menu__icon'],
34                 'weight': item['permissions__menu__weight'],
35                 'children': [{
36                     'title': item['permissions__title'],
37                     'url': item['permissions__url'],
38                     'id': item['permissions__id'],
39                 }]
40             }
41         else:
42             menu_dic[menu_id]['children'].append({
43                 'title': item['permissions__title'],
44                 'url': item['permissions__url'],
45                 'id': item['permissions__id'],
46             })
47 
48     request.session[settings.PERMISSION_SESSION_KEY] = permission_list
49     request.session[settings.MENU_SESSION_KEY] = menu_dic
权限信息查询和session中保存

步骤3.中间件权限校验,处理访问url归属问题 middlewares/rbac.py

 1 from django.utils.deprecation import MiddlewareMixin
 2 import re
 3 from django.conf import settings
 4 from django.shortcuts import HttpResponse,redirect,reverse
 5 
 6 class RbacMiddleware(MiddlewareMixin):
 7 
 8     def process_request(self,request):
 9         #获取当前的url
10         url = request.path_info
11 
12         #白名单
13         for i in settings.WHITE_LIST:
14             if re.match(i,url):
15                 return
16 
17         #获取权限信息
18         permission_list = request.session.get(settings.PERMISSION_SESSION_KEY)
19         if not permission_list:
20             return redirect(reverse('login'))
21         #权限校验
22 
23         for item in permission_list:
24             # i 里面有{url pid  id}
25             if re.match("^{}$".format(item['url']),url):
26                 #要显示的二级菜单的id
27                 pid = item.get('pid')
28                 id = item.get('id')
29                 #此步操作就是表示不管是pid还是id都是显示的二级菜单的id
30                 if pid:
31                     #当前访问的是子权限,找父权限显示
32                     request.current_menu_id = pid
33                 else:
34                     #当前访问的是父权限,也就是二级菜单,找自己显示
35                     request.current_menu_id = id
36                 return
37         return HttpResponse('您没有访问的权限')
中间件处理访问的权限url归属问题

步骤4.自定义模板中二级菜单id和session中存的匹配成功

from django import template
import re
from luffy_permission import settings
from collections import OrderedDict

register = template.Library()
#自定义模板
@register.inclusion_tag('menu.html')
def menu(request):
    menu_dic = request.session.get(settings.MENU_SESSION_KEY)
    url = request.path_info  
    order_dic = OrderedDict()  
    for i in sorted(menu_dic,key=lambda n:menu_dic[n]['weight'],reverse=True):
        order_dic[i] = item = menu_dic[i] 
    # for item in order_dic.values(): 
        item['class'] = 'hide'  
        for i in item['children']: 
            if i['id'] == request.current_menu_id:#session中的id和访问的二级菜单id匹配
                i['class'] = 'active' 
                item['class'] = '' 
                break
    return {'menu_list':order_dic.values()}
自定义模板

猜你喜欢

转载自www.cnblogs.com/CrazySheldon1/p/10447685.html