-解決版本的BUG,即,當咱們點擊添加/刪除/編輯時,菜單的首頁都會縮小,按理說:不該該縮小。css
-看看最終的實現:html
點擊添加以後,注意看左邊的菜單管理,按理是不該該縮小的,可是以前的版本2是會縮小的,因此須要解決這個問題。jquery
解決方案思路:數據庫
解決: 1.找到當前點擊進入的url,找到這個url的組,讓這個組默認選中菜單就能夠。 - 請求url:request.path_info - 全部的url; ..... -以上兩個一一匹配,成功以後,找到組id,經過組id找到當前組裏的"is_menu"=True的這條記錄, 在它後面加個active = True爲默認被選中。而後須要再一次循環,把is_menu爲True取出來,讓這兩生成菜單就能夠了。 前提:一組一個菜單 2.修改數據庫的記錄。 1.方法1:在權限表加一個組內菜單的字段,自關聯。null 就爲菜單 /userinfo/ list null 組1 /userinfo/add add 1 組1 /userinfo/edit edit 1 組1 /userinfo/del del 1 組1 /order/ list null 組2 /order/add add 5 組2 /order/edit edit 5 組2 /order/del del 5 組2 2.方法2: 設一個菜單字典: menu_dict = { 1:{'id':1,'title':'用戶列表','url':'/userinfo/','menu_gp_id':None,'menu_id':1,'menu_title':'菜單管理',active=True} 5:{'id':5,'title':'訂單列表','url':'/order/','menu_gp_id':None,'menu_id':2,'menu_title':'訂單管理'} } current_url = request.path_info for item in menu_list: url = item['url'] regex = '^{0}$'format(url) if re.match(regex,current_url): menu_gp_id = item['menu_gp_id'] if not menu_gp_id: #給本身加active = True,下面兩個方式均可以用,由於用的是同一個引用。 item['active'] = True menu_dict[item]['id']['active']=True else: menu_dict[menu_gp_id]['active'] = True
app01/views.py:django
import re from django.shortcuts import render,redirect,HttpResponse from django.conf import settings from rbac import models from rbac.service.init_permission import init_permission def login(request): if request.method == "GET": return render(request,'login.html') else: user = request.POST.get('user') pwd = request.POST.get('pwd') user = models.User.objects.filter(username=user,password=pwd).first() print(request.POST) if not user: return render(request, 'login.html') init_permission(user,request) return redirect('/index/') def index(request): return HttpResponse('歡迎登陸') class BasePagePermission(object): def __init__(self,code_list): self.code_list = code_list def has_add(self): if "add" in self.code_list: return True def has_edit(self): if 'edit' in self.code_list: return True def has_del(self): if 'del' in self.code_list: return True def userinfo(request): page_permission = BasePagePermission(request.permission_code_list) data_list = [ {'id':1,'name':'xxx1'}, {'id':2,'name':'xxx2'}, {'id':3,'name':'xxx3'}, {'id':4,'name':'xxx4'}, {'id':5,'name':'xxx5'}, ] return render(request,'userinfo.html',{'data_list':data_list,'page_permission':page_permission}) def userinfo_add(request): page_permission = BasePagePermission(request.permission_code_list) return render(request, 'userinfo_add.html', { 'page_permission': page_permission}) class OrderPagePermission(BasePagePermission): def has_report(self): if 'report' in self.code_list: return True def order(request): order_permission = OrderPagePermission(request.permission_code_list) return render(request,'order.html') def order_add(request): return HttpResponse('添加訂單頁面')
settings.py:session
urls.py:app
from django.conf.urls import url
from django.contrib import admin
from rbac import views
from app01 import views as app01_views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test/', views.test),
url(r'^login/', app01_views.login),
url(r'^index/', app01_views.index),
url(r'^userinfo/$', app01_views.userinfo),
url(r'^userinfo/add/$', app01_views.userinfo_add),
url(r'^order/$', app01_views.order),
url(r'^order/add/$', app01_views.order_add),
]
rbac\middlewares\rbac.py:ide
import re from django.shortcuts import redirect,HttpResponse from django.conf import settings class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response class RbacMiddleware(MiddlewareMixin): def process_request(self,request): # 1. 獲取當前請求的URL # request.path_info # 2. 獲取Session中保存當前用戶的權限 # request.session.get("permission_url_list') current_url = request.path_info # 當前請求不須要執行權限驗證 for url in settings.VALID_URL: if re.match(url,current_url): return None permission_dict = request.session.get(settings.PERMISSION_URL_DICT_KEY) if not permission_dict: return redirect('/login/') flag = False for group_id,code_url in permission_dict.items(): for db_url in code_url['urls']: regax = "^{0}$".format(db_url) if re.match(regax, current_url): request.permission_code_list = code_url['codes'] flag = True break if flag: break if not flag: return HttpResponse('無權訪問')
rbac\service\init_permission.pyui
from django.conf import settings def init_permission(user,request): """ 初始化權限信息,獲取權限信息並放置到session中。 :param user: :param request: :return: """ permission_list = user.roles.values('permissions__id', 'permissions__title', # 用戶列表 'permissions__url', 'permissions__code', 'permissions__menu_gp_id', # 組內菜單ID,Null表示是菜單 'permissions__group_id', 'permissions__group__menu_id', # 菜單ID 'permissions__group__menu__title',# 菜單名稱 ).distinct() # 菜單相關(之後再匹配) sub_permission_list = [] for item in permission_list: tpl = { 'id':item['permissions__id'], 'title':item['permissions__title'], 'url':item['permissions__url'], 'menu_gp_id':item['permissions__menu_gp_id'], 'menu_id':item['permissions__group__menu_id'], 'menu_title':item['permissions__group__menu__title'], } sub_permission_list.append(tpl) request.session[settings.PERMISSION_MENU_KEY] = sub_permission_list # 權限相關 result = {} for item in permission_list: group_id = item['permissions__group_id'] code = item['permissions__code'] url = item['permissions__url'] if group_id in result: result[group_id]['codes'].append(code) result[group_id]['urls'].append(url) else: result[group_id] = { 'codes':[code,], 'urls':[url,] } request.session[settings.PERMISSION_URL_DICT_KEY] = result
rbac.cssthis
.item-permission{ padding: 3px 10px; } .item-permission a{ display: block; } .item-permission a.active{ color: red; } .hide{ display: none; }
rbac.js
/** * Created by Administrator on 2017/11/8. */ $(function () { $('.item-title').click(function () { if($(this).next().hasClass('hide')){ $(this).next().removeClass('hide') }else{ $(this).next().addClass('hide') } }) });
rbac\templatetags\rbac.py
import re from django.template import Library from django.conf import settings register = Library() @register.inclusion_tag("xxxxx.html") def menu_html(request): """ 去Session中獲取菜單相關信息,匹配當前URL,生成菜單 :param request: :return: """ menu_list = request.session[settings.PERMISSION_MENU_KEY] current_url = request.path_info menu_dict = {} for item in menu_list: if not item['menu_gp_id']: menu_dict[item['id']] = item for item in menu_list: regex = "^{0}$".format(item['url']) if re.match(regex,current_url): menu_gp_id = item['menu_gp_id'] if menu_gp_id: menu_dict[menu_gp_id]['active'] = True else: menu_dict[item['id']]['active'] = True result = {} for item in menu_dict.values(): active = item.get('active') menu_id = item['menu_id'] if menu_id in result: result[menu_id]['children'].append({ 'title': item['title'], 'url': item['url'],'active':active}) if active: result[menu_id]['active'] = True else: result[menu_id] = { 'menu_id':item['menu_id'], 'menu_title':item['menu_title'], 'active':active, 'children':[ { 'title': item['title'], 'url': item['url'],'active':active} ] } return {'menu_dict':result}
rbac\models.py
from django.db import models class Menu(models.Model): """ 菜單組 """ title = models.CharField(max_length=32) class Group(models.Model): """ 權限組 """ caption = models.CharField(verbose_name='組名稱',max_length=16) menu = models.ForeignKey(verbose_name='所屬菜單',to='Menu',default=1) class Permission(models.Model): """ 權限表 """ title = models.CharField(verbose_name='標題',max_length=32) url = models.CharField(verbose_name="含正則URL",max_length=64) menu_gp = models.ForeignKey(verbose_name='組內菜單',to='Permission',null=True,blank=True,related_name='x1') code = models.CharField(verbose_name="代碼",max_length=16) group = models.ForeignKey(verbose_name='所屬組',to="Group") class Meta: verbose_name_plural = "權限表" def __str__(self): return self.title class User(models.Model): """ 用戶表 """ username = models.CharField(verbose_name='用戶名',max_length=32) password = models.CharField(verbose_name='密碼',max_length=64) email = models.CharField(verbose_name='郵箱',max_length=32) roles = models.ManyToManyField(verbose_name='具備的全部角色',to="Role",blank=True) class Meta: verbose_name_plural = "用戶表" def __str__(self): return self.username class Role(models.Model): """ 角色表 """ title = models.CharField(max_length=32) permissions = models.ManyToManyField(verbose_name='具備的全部權限',to='Permission',blank=True) class Meta: verbose_name_plural = "角色表" def __str__(self): return self.title
layout.html:
{% load rbac %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/static/rbac/rbac.css" /> <title>Title</title> </head> <body> <div style="float: left;width: 20%;height: 500px;background-color: #dddddd"> {% menu_html request %} </div> <div style="float: left;width: 80%"> {% block content %}{% endblock %} </div> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/rbac/rbac.js"></script> </body> </html>
xxxxx.html:
{% for k,item in menu_dict.items %} <div class="item"> <div class="item-title">{{ item.menu_title }}</div> {% if item.active %} <div class="item-permission"> {% else %} <div class="item-permission hide"> {% endif %} {% for v in item.children %} {% if v.active %} <a href="{{ v.url }}" class="active">{{ v.title }}</a> {% else %} <a href="{{ v.url }}">{{ v.title }}</a> {% endif %} {% endfor %} </div> </div> {% endfor %}