Django--CRM--菜单排序等
一 . 菜单排序
1.我们想把菜单排序.首先给菜单加上权重,权重大的排在上面, 这就要在菜单表上加上一个权重字段.
2. 我们在菜单表里面把权重改一下
3. 需要把权重字段的信息拿出来放到session中去
4. 在自定义过滤器里面进行排序 然后其他的不用改就会显示成排序后的菜单
from django import template
from django.conf import settings
from collections import OrderedDict
register = template.Library()
@register.inclusion_tag('menu.html')
def my_menu(request):
url = request.path
# 二级菜单
menu_dict = request.session[settings.MENU_SESSION_KEY] # 不能在这循环,需要模板里面循环
# 按照添加的顺序进行展示 有序字典
ordered_dict = OrderedDict()
# ret是按照权重排完序的key
ret = sorted(menu_dict, key=lambda x: menu_dict[x]['weight'], reverse=True)
for i in ret:
ordered_dict[i] = menu_dict[i]
return {'menu_list': ordered_dict.values()}
二 . 二级菜单选中并且展开
# 实现思路
1. 当我们点击二级菜单的时候, 让他显示被选中的状态,需要class="active"
2. 进入菜单页面的时候,除了输入的二级菜单对应的一级菜单外,其他的一级菜单都应该收起来
3. 当我们点击另一个一级菜单的时候, 其他的一级菜单全部都收起来
来看一下效果
三. 非菜单权限的归属
上面的操作有点瑕疵:
造成上面的原因是添加和编辑等和二级菜单没啥关系,影响不了二级菜单的展开与隐藏, 解决这个问题,需要把他们添加一对多的关系
看一下权限表
1 . 由上图可知, 如果点击的是编辑增加等标签,他的parent_id就是二级菜单的id, 这样我们就可以通过点击添加或者编辑找到二级标签的id,
那么我们就可以在自定义过滤器中判断,如果拿到的是二级id,那么就让这个菜单添加被选中并且展开的状态
2 . 我们需要把parent_id 和 二级菜单的id放到session中去
然后我们需要在权限验证的中间件中拿到二级菜单的id
1 from django.utils.deprecation import MiddlewareMixin 2 from django.shortcuts import HttpResponse, redirect 3 from django.conf import settings 4 import re 5 6 class RbacMiddleWare(MiddlewareMixin): 7 def process_request(self, request): 8 # 获取当前访问的页面 9 url = request.path 10 # print('>>>>>', url) 11 # 为了让index页面正常不报错 12 request.current_menu_id = None 13 # 在中间件中那 用反射 14 # setattr(request, settings.CURRENT_MENU_ID, None) 15 16 # 白名单 17 for i in settings.WHITE_LIST: 18 # match 匹配上得到一个对象,匹配不上返回None 19 if re.match(i, url): 20 return 21 # 获取登录状态 22 is_login = request.session['is_login'] 23 # 没有登录跳转登录页面 24 if not is_login: 25 return redirect('login') 26 27 # 免认证 28 for i in settings.NO_PERMISSION_LIST: 29 # match 匹配上得到一个对象,匹配不上返回None 30 if re.match(i, url): 31 return 32 33 # 获取当前用户的权限, 要用get去拿,没有显示None,[]就会报错 34 permission_list = request.session.get(settings.PERMISSION_SESSION_KEY) 35 # print(permission_list) 36 # 权限的校验 37 for permission in permission_list: 38 # print('>>>>',permission) 39 if re.match(f'^{permission.get("url")}$', url): 40 41 pid = permission.get('pid') 42 id = permission.get('id') 43 if pid: 44 # 当前访问的是添加编辑的功能 45 request.current_menu_id = pid # 用request才能传过去 46 # 用反射 47 # setattr(request, settings.CURRENT_MENU_ID, pid) 48 else: 49 # 访问的是二级菜单 50 request.current_menu_id = id 51 # 用反射 52 # setattr(request, settings.CURRENT_MENU_ID, id) 53 return 54 # 没有匹配成功 55 return HttpResponse('你的level不够!!')
当然,可以以配置到settings中去, 操作方法在上面写了,注释的那个就是
四 . 路径导航
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse, redirect from django.conf import settings import re class RbacMiddleWare(MiddlewareMixin): def process_request(self, request): # 获取当前访问的页面 url = request.path # 当前访问的路径id request.current_menu_id = None # 路径导航(面包线导航)的列表 request.breadcrumb_list = [{'title': '首页', 'url': '/index/'}] # 白名单 for i in settings.WHITE_LIST: # match 匹配上得到一个对象,匹配不上返回None if re.match(i, url): return # 获取登录状态 is_login = request.session['is_login'] # 没有登录跳转登录页面 if not is_login: return redirect('login') # 免认证 for i in settings.NO_PERMISSION_LIST: # match 匹配上得到一个对象,匹配不上返回None if re.match(i, url): return # 获取当前用户的权限, 要用get去拿,没有显示None,[]就会报错 permission_dict = request.session.get(settings.PERMISSION_SESSION_KEY) # 权限的校验 for permission in permission_dict.values(): if re.match(f'^{permission.get("url")}$', url): pid = permission.get('pid') id = permission.get('id') if pid: # 当前访问的是添加编辑的功能 request.current_menu_id = pid # 用request才能传过去 # 当点击添加或者编辑的时候就走的这里 parent = permission_dict[str(pid)] request.breadcrumb_list.append({'url': parent['url'], 'title': parent['title']}) else: # 访问的是二级菜单 request.current_menu_id = id # 如果没有pid就证明是二级菜单 request.breadcrumb_list.append({'url': permission['url'], 'title': permission['title']}) return # 没有匹配成功 return HttpResponse('你的level不够!!')
五 . 权限粒度控制按钮级别
权限粒度控制按钮级别意思就是你有这个权限给你展示这个按钮,你没有这个权限就不给你展示
思路:
1. 把用户的所有权限放到一个列表里面
2. 如果前端展示的按钮在用户的权限列表了,那么就显示
3. 由于url的别名不会总该,所以这里我们用别名来表示权限的url
4. 用url的别名, 要把别名写到数据库
5. 在权限表里面加一个别名字段,并且这个name要是唯一的, 要注意的是, 这个字段是后添加的, 需要先设置default, 但是不能直接填unique=True
6. 迁移完之后,把别名一一对应手动填写到权限表的name字段
7. 再到name字段中添加unique=True, 然后在进行数据库迁移
8. 我们需要获得数据库中的name字段的数据,这样我们可以把permission_dict[i['permissions__id']] 改为 permission_dict[i['permissions__name']] 因为都是唯一的
由于key 从id 改为 name了,所以我们的路径导航里面的用到的permissions__id也要做出相应的改变,之前用的是二级菜单的id, 由于存在关系,所以可以通过pid找到
二级菜单的name,然后中间件中的引用的str(pid)也要改成name
1 from django.utils.deprecation import MiddlewareMixin 2 from django.shortcuts import HttpResponse, redirect 3 from django.conf import settings 4 import re 5 6 class RbacMiddleWare(MiddlewareMixin): 7 def process_request(self, request): 8 # 获取当前访问的页面 9 url = request.path 10 11 # 当前访问的路径id 12 request.current_menu_id = None 13 14 # 路径导航(面包线导航)的列表 15 request.breadcrumb_list = [{'title': '首页', 'url': '/index/'}] 16 17 # 白名单 18 for i in settings.WHITE_LIST: 19 # match 匹配上得到一个对象,匹配不上返回None 20 if re.match(i, url): 21 return 22 # 获取登录状态 23 is_login = request.session['is_login'] 24 # 没有登录跳转登录页面 25 if not is_login: 26 return redirect('login') 27 28 # 免认证 29 for i in settings.NO_PERMISSION_LIST: 30 # match 匹配上得到一个对象,匹配不上返回None 31 if re.match(i, url): 32 return 33 34 # 获取当前用户的权限, 要用get去拿,没有显示None,[]就会报错 35 permission_dict = request.session.get(settings.PERMISSION_SESSION_KEY) 36 # print(permission_list) 37 # 权限的校验 38 for permission in permission_dict.values(): 39 # print('>>>>',permission) 40 if re.match(f'^{permission.get("url")}$', url): 41 42 pid = permission.get('pid') 43 id = permission.get('id') 44 pname = permission.get('pname') # 路径导航改成pname 45 if pid: 46 # 当前访问的是添加编辑的功能 47 request.current_menu_id = pid # 用request才能传过去 48 49 # 当点击添加或者编辑的时候就走的这里 50 parent = permission_dict[pname] 51 request.breadcrumb_list.append({'url': parent['url'], 'title': parent['title']}) 52 53 else: 54 # 访问的是二级菜单 55 request.current_menu_id = id 56 57 # 如果没有pid就证明是二级菜单 58 request.breadcrumb_list.append({'url': permission['url'], 'title': permission['title']}) 59 return 60 # 没有匹配成功 61 return HttpResponse('你的level不够!!')
9 . 自定义过滤器