设计菜单管理问题:
图片.png
1.如何生成菜菜单
2.怎么让这些菜单分级显示并且如果当前访问的url权限默认
展开如果是组内菜单就加粗或者变红
3.非菜单url,默认选中原菜单。(如果你是点击用户列表进来的
那么你看到页面了,如果你点击添加的时候,你的那个用户列看不见了
这就不好了。所以要设计当你点击添加按钮的时候,那个用户列表被默认选中)
菜单管理
菜单一:
用户管理
权限管理
菜单二:
订单管理
角色管理
分级做了菜单。这些菜单该显示什么菜单?是当前用户登录之后从数据库拿到用户拥有的权限,然后把权限搞成菜单
在表里面设计了一个组内菜单(自关联),当menu_gp_id为NULL就代表可以作为菜单
图片.png
1.在models中添加Menu对象(表)以及和group建立起一对多的关系
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')
class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name='标题',max_length=32)
url = models.CharField(verbose_name="含正则URL",max_length=64)
is_menu = models.BooleanField(verbose_name="是否是菜单")
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
models
2.初始化获取菜单信息+权限信息
from django.conf import settings
def init_permission(user,request):
"""
初始化权限信息,获取权限信息并放置到session中。
:param user:
:param request:
:return:
"""
permission_list = user.roles.values('permissions__title', # 用户列表
'permissions__url',
'permissions__code',
'permissions__is_menu', # 是否是菜单
'permissions__group_id',
'permissions__group__menu_id', # 菜单ID
'permissions__group__menu__title',# 菜单名称
).distinct()
menu_list = []
# 去掉不是菜单的URL
for item in permission_list:
if not item['permissions__is_menu']:
continue
tpl = {
'menu_id':item['permissions__group__menu_id'],
'menu_title':item['permissions__group__menu__title'],
'title':item['permissions__title'],
'url':item['permissions__url'],
'active':False,
}
menu_list.append(tpl)
request.session[settings.PERMISSION_MENU_KEY] = menu_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
init_permission.py
结构化数据示例:
mport re
menu_list = [
{'menu_id':1, 'menu_title':'菜单一','title':'用户列表','url':'/userinfo/','active':False},
{'menu_id':1, 'menu_title':'菜单一','title':'订单列表','url':'/order/','active':False},
{'menu_id':2, 'menu_title':'菜单二','title':'xxx列表','url':'/xxx/','active':False},
{'menu_id':2, 'menu_title':'菜单二','title':'iii列表','url':'/uuu/','active':False},
]
current_url = "/userinfo/"
res={}
for tem in menu_list:
mid=tem["menu_id"]
mtitle=tem["menu_title"]
title=tem["title"]
url=tem["url"]
active=False
if re.match(url,current_url):
active=True
if mid in res:
res[mid]["children"].append({"title":title,"url":url,"active":active})
if active:
res[mid]["active"]=True
else:
res[mid]={
"menu_id":mid,
"menu_title":mtitle,
"active":active,
"children":[
{"title":title,"url":url,"active":True},
]
}
print(res)
结果:
aa={
1:
{
'menu_id': 1,
'menu_title': '菜单一',
'active': True,
'children': [{'title': '用户列表', 'url': '/userinfo/', 'active': True},
{'title': '订单列表', 'url': '/order/', 'active': True}]
},
2:
{
'menu_id': 2,
'menu_title': '菜单二',
'active': True,
'children': [{'title': 'xxx列表', 'url': '/xxx/', 'active': True},
{'title': 'iii列表', 'url': '/uuu/', 'active': True}]
}
}
3.显示多级菜单
模块中操作
其中菜单部分由自定义标签生产
具体展示页面则用模块继承:如userinfo
a.base.html
{% load rbac %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/rbac/rbac.css">
</head>
<body>
<div style="float: left;width: 20%;height: 900px;background-color: darkgrey">
{% menu_html request %}
</div>
<div style="float: left;width: 80%">
{% block content %}
{% endblock %}
</div>
</body>
<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/rbac/rbac.js"></script>
</html>
b.userinfo.html
{% extends "base.html" %}
{% block content %}
{% if pagepermission.has_add %}
<p><a href="">添加</a></p>
{% endif %}
<table>
<thead>
<th>id</th>
<th>name</th>
<th>操作</th>
</thead>
<tbody>
{% for foo in data_list %}
<tr>
<td>{{ foo.id }}</td>
<td>{{ foo.name }}</td>
<td>
{% if pagepermission.has_edit %}
<a href="#">编辑</a>
{% endif %}
{% if pagepermission.has_del %}
<a href="#">删除</a>
{% endif %}
</td>
</tr>
{% endfor %}
{% endblock %}
c.建立自定义标签
rbac/templatetags/rbac.py
import re
from django.template import Library
from django.conf import settings
register = Library()
@register.inclusion_tag("menuList.html")
def menu_html(request):
menu_list = request.session[settings.PERMISSION_MENU_KEY]
current_url = request.path_info
result = {}
for item in menu_list:
url = item['url']
regex = "^{0}$".format(url)
active = False
if re.match(regex,current_url):
active = True
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': menu_id,
'menu_title': item['menu_title'],
'active': active,
'children': [
{'title': item['title'], 'url': item['url'], 'active': active},
]
}
return {'menu_dict':result}
rbac.py
d.menulist.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_permissions">
{% else %}
<div class="item_permissions hide">
{% endif %}
{% for v in item.children %}
{% if v.active %}
<a href="#" class="active">{{ v.title }}</a>
{% else %}
<a href="#">{{ v.title }}</a>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
e.css和js
在rbac建立static/rbac目录在其中创建rbac.css和rbac.js
.item_permissions{
padding: 3px 10px;
}
.item_permissions a{
display: block;
}
.item_permissions a.active{
color: red;
}
.hide{
display: none;
}
rbac.css
···
$(function () {
$(".item_title").click(function () {
$(this).next().toggleClass("hide")
});
})
···
.四.菜单展示的改进
因为当我们对用户部分进行增删改查的时,用户列表也应该展开的,但是我们上面所写的当我们点击增加删除编辑按钮时,用户菜单会闭合而不是展开的对此我们要进行一些改进
1.在权限表中增加字段menu_gp,并删除is_menu字段
from django.db import models
class Menu(models.Model):
'''
菜单表
'''
title=models.CharField(max_length=32,verbose_name="菜单名称")
class Group(models.Model):
'''
权限组
'''
caption=models.CharField(max_length=32,verbose_name="组名称")
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)
# is_menu = models.BooleanField(verbose_name="是否是菜单")
menu_gp=models.ForeignKey(verbose_name="组内菜单",to="Permission",null=True,blank=True)
code=models.CharField(max_length=32,verbose_name="代码",default="list")
group=models.ForeignKey(verbose_name="s所在权限组",to="Group",default=1)
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
moedels.py
2.修改初始化中菜单
init_permission.py
from django.conf import settings
def init_permission(user,request):
"""
初始化权限信息,获取权限信息并放置到session中。
:param user:
:param request:
:return:
"""
permission_list = user.roles.values('permissions__title',
"permissions__code",
"permissions__id",
'permissions__url',
'permissions__menu_gp_id',
"permissions__group__id",
"permissions__group__menu_id",
"permissions__group__menu__title",
).distinct()
menu_list=[]
for item in permission_list:
tpl={
"id":item["permissions__id"],
"title":item["permissions__title"],
"menu_title":item["permissions__group__menu__title"],
"url":item["permissions__url"],
"menu_id":item["permissions__group__menu_id"],
"menu_gp_id":item["permissions__menu_gp_id"],
}
menu_list.append(tpl)
request.session[settings.PERMISSIONS_MENU_KEY]=menu_list
# menu_list=[]
# for item in permission_list:
# if not item["permissions__is_menu"]:
# continue
#
# tpl={
# "menu_id":item["permissions__group__menu_id"],
# "menu_title":item["permissions__group__menu__title"],
# "title":item["permissions__title"],
# "url":item["permissions__url"],
# "active":False,
# }
#
# menu_list.append(tpl)
# print(menu_list)
# request.session[settings.PERMISSIONS_MENU_KEY]=menu_list
#权限管理
result={}
for item in permission_list:
groupid=item["permissions__group__id"]
code=item["permissions__code"]
url=item["permissions__url"]
if groupid in result:
result[groupid]["codes"].append(code)
result[groupid]["urls"].append(url)
else:
result[groupid]={
"codes":[code,],
"urls":[url,]
}
print(result)
request.session[settings.PERMISSIONS_URL_DICT_KEY] = result
init_permission.py
3.修改定义标签
rbac.py
import re
from django.conf import settings
from django.template import Library
register = Library()
@register.inclusion_tag("menuList.html")
def menu_html(request):
menu_list=request.session.get(settings.PERMISSIONS_MENU_KEY)
currenturl=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,currenturl):
menu_gp_id=item["menu_gp_id"]
if not menu_gp_id:
menu_dict[item["id"]]["active"]=True
else:
menu_dict[item["menu_gp_id"]]["active"]=True
'''
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': '菜单2'}}
'''
print(menu_dict,"11111111111111111111111111111111111111111111")
result = {}
for item in menu_dict.values():
menu_id=item["menu_id"]
menu_title=item["menu_title"]
active=item.get("active")
url=item["url"]
title=item["title"]
if menu_id in result:
result[menu_id]["children"].append({"title":title,"url":url,"active":active})
if active:
result[menu_id]["active"]=True
else:
result[menu_id]={
"menu_id":menu_id,
"menu_title":menu_title,
"active":active,
"children":[
{"title":title,"url":url,"active":active},
]
}
print(result)
# for item in menu_list:
# menu_id=item["menu_id"]
# menu_title=item["menu_title"]
# title=item["title"]
# url=item["url"]
# active=False
# regex="^{0}$".format(url)
# if re.match(regex,currenturl):
# active=True
#
# if menu_id in result:
# result[menu_id]["children"].append({{"title":title,"url":url,"active":active},})
# if active:
# result[menu_id]["active"]=active
# else:
# result[menu_id]={
# "menu_id":menu_id,
# "menu_title":menu_title,
# "active":active,
# "children":[
# {"title":title,"url":url,"active":active},
# ]
# }
# print(result)
return {"menu_dict":result}
rbac.py
其他不做修改