二级菜单优化功能
Posted crazysheldon1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二级菜单优化功能相关的知识,希望对你有一定的参考价值。
二级菜单的功能优化---渐入佳境
功能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
步骤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(‘您没有访问的权限‘)
步骤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()}
以上是关于二级菜单优化功能的主要内容,如果未能解决你的问题,请参考以下文章