crm 动态一级二级菜单
之前代码菜单是写是的
如何 让他 动态 生成了 首先 添加 2个字段
admin.py 更改 显示
from django.contrib import admin from rbac import models # Register your models here. class PermissionAdmin(admin.ModelAdmin): list_display = ['url', 'title','is_menu','icon']#列表显示 list_editable = ['title','is_menu','icon']#可编辑 admin.site.register(models.Permission, PermissionAdmin) admin.site.register(models.Role) admin.site.register(models.User)
然后进入 admin 把设为 一级菜单的 图标设置上去
auth.py 进行 mode筛选
def login(request): if request.method == 'POST': # 获取用户名和密码 user = request.POST.get('user') pwd = request.POST.get('pwd') # 去数剧库进行筛选 obj = models.User.objects.filter(name=user, pwd=pwd).first() if not obj: return render(request, 'login.html') permission_query = obj.roles.filter(permissions__url__isnull=False).values('permissions__url', 'permissions__title','permissions__is_menu','permissions__icon').distinct() #通过查询到的用户的obj反查角色表,values 正向查询当前用户的权限表的url信息 title permission_list=[]#存放权限信息 menu_list=[]#存放菜单信息 for item in permission_query: permission_list.append({'url':item['permissions__url']}) if item.get('permissions__is_menu'): menu_list.append({'url':item['permissions__url'],'icon':item['permissions__icon'],'title':item['permissions__title']}) # print('1111',permission_query) # <QuerySet [{'permissions__url': '/index/', 'permissions__title': '首页'}]> #将权限信息写入到session request.session[settings.PERMISSION_SESSION_KEY]=permission_list #将菜单 信息 写入session request.session[settings.MENU_SESSION_KEY]=menu_list request.session['is_login'] = True return redirect(reverse('index')) return render(request, 'login.html')
settings.py中定义
# 白名单 WHITE_LIST = [ r'^/login/$', r'^/reg/$', r'^/admin/.*', ] # 免认证的地址 需要登录 不行权限校验 NO_PERMISSION_LIST = [ '/index/' ] #权限信息url key PERMISSION_SESSION_KEY='permissions' #存放菜单信息 MENU_SESSION_KEY='menus'
更改一下 rbacapp中 更改 中间件中 middlewares/rbac.py 相应的值
# 获取当前用户的权限 permission_list = request.session[settings.PERMISSION_SESSION_KEY] print(permission_list) # 权限的校验 for i in permission_list: if re.match('^{}$'.format(i['url']), url): return # 没匹配成功 没有权限 return HttpResponse('没有访问的权限')
layout.html中 跟改显示 这样虽然成功了 但是还是写死了menus
<div class="static-menu"> {# <a href="/customer/list/" class="active">#} {# <span class="icon-wrap"><i class="fa fa-connectdevelop"></i></span> 客户管理</a>#} {# <a href="/payment/list/">#} {# <span class="icon-wrap"><i class="fa fa-code-fork"></i></span> 账单管理</a>#} {% for item in request.session.menus %} <a href="{{ item.url }}"> <span class="icon-wrap"><i class="fa fa-code-fork"></i></span> {{ item.title }}</a> {% endfor %} </div>
如何解决?
自定义 inclusion_tag
创建 templatetags目录 rbac.py
from django import template from django.conf import settings register=template.Library() import re @register.inclusion_tag('menu.html') def menu(request): menu_list=request.session.get(settings.MENU_SESSION_KEY) for item in menu_list: url=item['url'] if re.match('^{}$'.format(url),request.path_info): item['class']='active' return {'menu_list':menu_list}
menu.html
<div class="static-menu"> {% for item in menu_list%} <a href="{{ item.url }}" class="{{ item.class }}"> <span class="icon-wrap"><i class="fa fa-code-fork"></i></span> {{ item.title }}</a> {% endfor %} </div>
为了 下次 直接调用rbac 整合
把之前的判断 web views中的auth.py中的 查询写入session部分 移动到rbac/server/init_permission.py
from django.conf import settings def init_permission(request, obj): permission_query = obj.roles.filter(permissions__url__isnull=False).values('permissions__url', 'permissions__title', 'permissions__is_menu', 'permissions__icon').distinct() permission_list = [] # 存放权限 menu_list = [] # 存放菜单信息 for item in permission_query: permission_list.append({'url': item['permissions__url']}) if item.get('permissions__is_menu'): menu_list.append({'url': item['permissions__url'], 'icon': item['permissions__icon'], 'title': item['permissions__title']}) # 将权限写入session request.session[settings.PERMISSION_SESSION_KEY] = permission_list # 将菜单写入 session request.session[settings.MENU_SESSION_KEY] = menu_list request.session['is_login'] = True
if not obj: return redirect(reverse('login')) # 认证成功 进行权限信息初始化(权限、菜单) init_permission(request, obj) return redirect(reverse('index'))
把 web下的 templatetags 移动到rbac app下
自定义标签inclusion
把menu.html 移动到新建templates/rbac/中
把 css部分 移动到 static/css/menu.css
二级菜单调用自动生成
更改modes中的表字段 添加 menu表
进入 admin 进行 权限 划分
更改 server permission.py
# 权限的列表 permission_list = [] # 菜单的字典 menu_dict ={} for i in permission_query: # 把权限的信息放入permission_list permission_list.append({'url': i['permissions__url']}) menu_id = i.get('permissions__menu_id') if not menu_id: continue menu_dict.setdefault(menu_id, { 'title': i['permissions__menu__title'], 'icon': i['permissions__menu__icon'], 'children': [ ] }) menu_dict[menu_id]['children'].append({'title': i['permissions__title'], 'url': i['permissions__url']})
from django import template from django.conf import settings import re register = template.Library() @register.inclusion_tag('rbac/menu.html') def menu(request): menu_dict = request.session[settings.MENU_SESSION_KEY] return {'menu_list': menu_dict.values()}
rbac/static/rbac/css/menu.css
.left-menu .menu-body .static-menu { } .left-menu .menu-body .static-menu .icon-wrap { width: 20px; display: inline-block; text-align: center; } .left-menu .menu-body .static-menu a { text-decoration: none; padding: 8px 15px; border-bottom: 1px solid #ccc; color: #333; display: block; background: #efefef; background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #efefef), color-stop(1, #fafafa)); background: -ms-linear-gradient(bottom, #efefef, #fafafa); background: -moz-linear-gradient(center bottom, #efefef 0%, #fafafa 100%); background: -o-linear-gradient(bottom, #efefef, #fafafa); filter: progid:dximagetransform.microsoft.gradient(startColorStr='#e3e3e3', EndColorStr='#ffffff'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fafafa',EndColorStr='#efefef')"; box-shadow: inset 0px 1px 1px white; } .left-menu .menu-body .static-menu a:hover { color: #2F72AB; border-left: 2px solid #2F72AB; } .left-menu .menu-body .static-menu a.active { color: #2F72AB; border-left: 2px solid #2F72AB; } .multi-menu .item { background-color: white; } .multi-menu .item > .title { padding: 10px 5px; border-bottom: 1px solid #dddddd; cursor: pointer; color: #333; display: block; background: #efefef; background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #efefef), color-stop(1, #fafafa)); background: -ms-linear-gradient(bottom, #efefef, #fafafa); background: -o-linear-gradient(bottom, #efefef, #fafafa); filter: progid:dximagetransform.microsoft.gradient(startColorStr='#e3e3e3', EndColorStr='#ffffff'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fafafa',EndColorStr='#efefef')"; box-shadow: inset 0 1px 1px white; } .multi-menu .item > .body { border-bottom: 1px solid #dddddd; } .multi-menu .item > .body a { display: block; padding: 5px 20px; text-decoration: none; border-left: 2px solid transparent; font-size: 13px; } .multi-menu .item > .body a:hover { border-left: 2px solid #2F72AB; } .multi-menu .item > .body a.active { border-left: 2px solid #2F72AB; }
<div class="multi-menu"> {% for menu in menu_list %} <div class="item"> <div class="title"> <i class="fa {{ menu.icon }}"></i> {{ menu.title }}</div> <div class="body"> {% for child in menu.children %} <a href="{{ child.url }}"> {{ child.title }} </a> {% endfor %} </div> </div> {% endfor %} </div>
layout.html应用上
{% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>路飞学城</title> <link rel="shortcut icon" href="{% static 'imgs/luffy-study-logo.png' %} "> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %} "/> <link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %} "/> <link rel="stylesheet" href="{% static 'css/commons.css' %} "/> <link rel="stylesheet" href="{% static 'css/nav.css' %} "/> <link rel="stylesheet" href="{% static 'rbac/css/menu.css' %} "/> <style> body { margin: 0; } .no-radius { border-radius: 0; } .no-margin { margin: 0; } .pg-body > .left-menu { background-color: #EAEDF1; position: absolute; left: 1px; top: 48px; bottom: 0; width: 220px; border: 1px solid #EAEDF1; overflow: auto; } .pg-body > .right-body { position: absolute; left: 225px; right: 0; top: 48px; bottom: 0; overflow: scroll; border: 1px solid #ddd; border-top: 0; font-size: 13px; min-width: 755px; } .navbar-right { float: right !important; margin-right: -15px; } .luffy-container { padding: 15px; } </style> </head> <body> <div class="pg-header"> <div class="nav"> <div class="logo-area left"> <a href="#"> <img class="logo" src="{% static 'imgs/logo.svg' %}"> <span style="font-size: 18px;">路飞学城 </span> </a> </div> <div class="left-menu left"> <a class="menu-item">资产管理</a> <a class="menu-item">用户信息</a> <a class="menu-item">路飞管理</a> <div class="menu-item"> <span>使用说明</span> <i class="fa fa-caret-down" aria-hidden="true"></i> <div class="more-info"> <a href="#" class="more-item">管他什么菜单</a> <a href="#" class="more-item">实在是编不了</a> </div> </div> </div> <div class="right-menu right clearfix"> <div class="user-info right"> <a href="#" class="avatar"> <img class="img-circle" src="{% static 'imgs/default.png' %}"> </a> <div class="more-info"> <a href="#" class="more-item">个人信息</a> <a href="#" class="more-item">注销</a> </div> </div> <a class="user-menu right"> 消息 <i class="fa fa-commenting-o" aria-hidden="true"></i> <span class="badge bg-success">2</span> </a> <a class="user-menu right"> 通知 <i class="fa fa-envelope-o" aria-hidden="true"></i> <span class="badge bg-success">2</span> </a> <a class="user-menu right"> 任务 <i class="fa fa-bell-o" aria-hidden="true"></i> <span class="badge bg-danger">4</span> </a> </div> </div> </div> <div class="pg-body"> <div class="left-menu"> <div class="menu-body"> {# <a href="/customer/list/" class="active">#} {# <span class="icon-wrap"><i class="fa fa-connectdevelop"></i></span> 客户管理</a>#} {# <a href="/payment/list/">#} {# <span class="icon-wrap"><i class="fa fa-code-fork"></i></span> 账单管理</a>#} {% load rbac %} {% menu request %} </div> </div> <div class="right-body"> <div> <ol class="breadcrumb no-radius no-margin" style="border-bottom: 1px solid #ddd;"> <li><a href="#">首页</a></li> <li class="active">客户管理</li> </ol> </div> {% block content %} {% endblock %} </div> </div> <script src="{% static 'js/jquery-3.3.1.min.js' %} "></script> <script src="{% static 'plugins/bootstrap/js/bootstrap.js' %} "></script> <script> $('.multi-menu .title').click(function () { $(this).next().toggleClass('hide') }) </script> {% block js %} {% endblock %} </body> </html>
不怕大牛比自己牛,就怕大牛比自己更努力