目录权限封装成类
2018-03-20 本文已影响9人
两点半的杂货铺
一、思路
-
self.session_data(),初始化自身,用来做判断用户当前是否是登陆状态,如果是分别吧 url2action_dict self.menu_leaf_list self.menu_list ,从session获取的三个主要的封装获取,在重新赋给自己的属性
-
menu_data_list 用来整理当前用户的菜单和主菜单并把他们,进行整理合并
-
actions 判断当前url是否存在增删改查的访问权限
class MenuHelper(object):
def __init__(self,request,userid):
'''
self.current_url:获取用户当前地址,用来判断用户当前是否有访问地址权限
url2action_dict :获取用户的访问url和访问类型{url:[get,psot]}
menu_leaf_lis : 获取在菜单中显示的权限[{'id','url','菜单id','url_标题'}]
self.menu_list:获取所有菜单
:param request: django request
:param username: 用户名
'''
self.request = request
self.userid = userid
self.current_url = request.path_info
self.url2action_dict = None
self.menu_leaf_list =None
self.menu_list = None
self.session_data()
def session_data(self):
permission_dict = self.request.session.get('permission_info')
if permission_dict:
self.url2action_dict = permission_dict['url2action_dict']
self.menu_leaf_list = permission_dict['menu_leaf_list']
self.menu_list = permission_dict['menu_list']
else:
role_list = models.Role.objects.filter(user2role__u_id=self.userid)
#获取查出权限的所有连接去重
url2action_list = models.Url2Action.objects.\
filter(url2action2role__r__in=role_list).\
values('url__url','a__code').distinct()
#处理成url和[post]对应的键值对关系
url2action_dict = {}
for item in url2action_list:
if item['url__url'] in url2action_dict:
url2action_dict[item['url__url']].append(item['a__code'])
else:
url2action_dict[item['url__url']] = [item['a__code'],]
#获取获取url 所在的目录
menu_leaf_list = list(
models.Url2Action.objects.filter(url2action2role__r__in=role_list) \
.exclude(url__menu__isnull=True).
values('url__menu', 'url__caption', 'url_id','url__url').distinct()
)
#获取所有目录
menu_list = list(models.Menu.objects.values('id', 'caption', 'parent_id'))
self.request.session['permission_info'] = {
'url2action_dict': url2action_dict,
'menu_leaf_list': menu_leaf_list,
'menu_list': menu_list,
}
#权限菜单,和用户权限
def menu_data_list(self):
import re
open_leaf_parent_id = None
menu_leaf_dict = {}
for item in self.menu_leaf_list:
item = {
'id': item['url_id'],
'url': item['url__url'],
'caption': item['url__caption'],
'parent_id': item['url__menu'],
'status': True,
# 这个child加不加疑问?
'child': [],
# 判断菜单是否打开
'opend': False
}
if item['parent_id'] in self.menu_leaf_list:
menu_leaf_dict[item['parent_id']].append(item)
else:
menu_leaf_dict[item['parent_id']] = [item]
# 在数据库的url用正则表示,和用户的url做对比
if re.match(item['url'],self.current_url):
item['opend'] = True
open_leaf_parent_id = item['parent_id']
# {1: {'id': 1, 'caption': '菜单1', 'child': [], 'parent_id': None},}
# 创建一个字典在里面加一个child key
menu_dict = {}
for item in self.menu_list:
item['child'] = []
item['status'] = False
item['opend'] = False
menu_dict[item['id']] = item
# 有了菜单,有了用户数据
# 菜单{1: {'id': 1, 'caption': '菜单1', 'child': [], 'parent_id': None}.....}
# 用户所具有的菜单4: [{'id': 1, 'caption': '订单', 'child': [], 'parent_id': 4, 'url': 'dingdan.html'}]}
# 把两个菜单弄成一种格式
# 循环个人菜单和主菜单对比
for k, v in menu_leaf_dict.items():
menu_dict[k]['child'] = v
# 循环每一层的parent_id
parent_id = k
while parent_id:
menu_dict[parent_id]['status'] = True
parent_id = menu_dict[parent_id]['parent_id']
# 循环标记打开菜单
while open_leaf_parent_id:
menu_dict[open_leaf_parent_id]['opend'] = True
open_leaf_parent_id = menu_dict[open_leaf_parent_id]['parent_id']
result = []
for row in menu_dict.values():
# 找到主菜单,主菜单自关联是None
if not row['parent_id']:
result.append(row)
else:
menu_dict[row['parent_id']]['child'].append(row)
return result
#权限树
def menu_tree(self):
response = ' '
tpl = '''
<div class="'itme %s">
<div class="'title">%s</div>
<div class="content">%s</div>
</div>
'''
for row in self.menu_data_list():
if not row['status']:
continue
active = ''
if row['opend']:
active = 'active'
if 'url' in row:
response += '<a class=%s href="%s">%s</a>' % (active, row['url'], row['caption'])
else:
title = row['caption']
content = self.menu_content(row['child'])
response += tpl % (active, title, content)
return response
def menu_content(self,child_list):
response = ' '
tpl = '''
<div class="'itme %s">
<div class="'title">%s</div>
<div class="content">%s</div>
</div>
'''
for row in child_list:
if not row['status']:
continue
active = ''
if row['opend']:
active = 'active'
if 'url' in row:
response += '<a class=%s href="%s">%s</a>' % (active, row['url'], row['caption'])
else:
title = row['caption']
content = self.menu_content(row['child'])
response += tpl % (active, title, content)
return response
def actions(self):
import re
"""
检查当前用户是否对当前URL有权访问,并获取对当前URL有什么权限
"""
action_list = []
# 当前所有权限
# {
# '/index.html': ['GET',POST,]
# }
print(self.url2action_dict)
for k,v in self.url2action_dict.items():
if re.match(k,self.current_url):
action_list = v # ['GET',POST,]
break
return action_list
二、使用
-
逻辑在登录的时候判断用户名密码是否正确,如果正确调用分装的目录函数,对当前用户进行保存
def login(request):
if request.method == "GET":
return render(request,'login1.html')
else:
username = request.POST.get('username')
pwd = request.POST.get('pwd')
obj = models.userinfo.objects.filter(username=username,password=pwd).first()
if obj:
# obj.id, obj.username
# 当前用户信息放置session中
request.session['user_info'] = {'nid':obj.nid,'username':obj.username}
# 获取当前用户的所有权限
# 获取在菜单中显示的权限
# 获取所有菜单
# 放置session中
MenuHelper(request,obj.nid)
return redirect('/index.html')
else:
return HttpResponse('cuowu')
-
装饰器判断当前用户是否有访问权限
def permission(func):
#装饰器用来判断是否登录,和是否有这个url增删改查其中一个
def inner(request,*args,**kwargs):
print(dict(request.session))
user_info = request.session.get('user_info')
if not user_info:
return redirect('/login.html')
obj = MenuHelper(request,user_info['nid'])
action_list = obj.actions()
if not action_list:
return HttpResponse('无权限访问1111')
kwargs['action_list'] = obj.actions()
kwargs['menu_string'] = obj.menu_tree()
return func(request,*args,**kwargs)
return inner
-
使用
@permission
def index(request,**kwargs):
action_list = kwargs.get('action_list')
menu_string = kwargs.get('menu_string')
#装饰器判断完后在url具体判断是有增删改查哪一个
if "GET" in action_list:
result = models.User.objects.all()
else:
result = []
return render(request,'menu.html',{'menu_string':menu_string,'action_list':action_list})