python---权限管理和菜单生成
一:表结构(共八张表)
- from django.db import models
- # Create your models here.
- class User(models.Model):
- username = models.CharField(max_length=)
- pasword = models.CharField(max_length=)
- class Meta:
- verbose_name_plural = "用户表"
- def __str__(self):
- return self.username
- class Role(models.Model):
- caption = models.CharField(max_length=)
- class Meta:
- verbose_name_plural = "角色表"
- def __str__(self):
- return self.caption
- class User2Role(models.Model):
- u = models.ForeignKey("User")
- r = models.ForeignKey("Role")
- class Meta:
- verbose_name_plural = "用户角色分配表"
- def __str__(self):
- return "%s:%s"%(self.u.username,self.r.caption)
- class Action(models.Model):
- #/user.html?t=get 获取用户信息
- #/user.html?t=post 创建用户
- #/user.html?t=put 修改用户
- #/user.html?t=delete 删除用户
- # ---> get 查询
- # ---> post 增加
- # ---> put 修改
- # ---> delete 删除
- caption = models.CharField(max_length=)
- code = models.CharField(max_length=)
- class Meta:
- verbose_name_plural = "操作表"
- def __str__(self):
- return self.caption
- class Menu(models.Model):
- caption = models.CharField(max_length=)
- parent = models.ForeignKey("self",related_name="p",null=True,blank=True)
- class Meta:
- verbose_name_plural="菜单表"
- def __str__(self):
- return self.caption
- class Permission(models.Model):
- #/user.html 用户管理
- caption = models.CharField(max_length=)
- url = models.CharField(max_length=)
- menu = models.ForeignKey("Menu",null=True)
- class Meta:
- verbose_name_plural = "权限"
- def __str__(self):
- return self.caption
- class Permission2Action(models.Model):
- p = models.ForeignKey("Permission")
- a = models.ForeignKey("Action")
- class Meta:
- verbose_name_plural = "权限表"
- def __str__(self):
- return "%s-%s:%s?t=%s"%(self.p.caption,self.a.caption,self.p.url,self.a.code)
- class Permission2Action2Role(models.Model):
- p2a = models.ForeignKey("Permission2Action")
- r = models.ForeignKey("Role")
- class Meta:
- verbose_name_plural = "角色权限分配表"
- def __str__(self):
- return "%s:%s"%(self.r.caption,self.p2a)
二:登录业务
- def login(request):
- if request.method == "GET":
- return render(request,"login.html")
- else:
- username = request.POST.get("username")
- pasword = request.POST.get("password")
- obj = models.User.objects.filter(username=username,pasword=pasword).get()
- if obj:
- #获取用户信息,放在session中
- request.session['user_info'] = {'nid':obj.id,'username':obj.username}
- #获取所有权限
- #获取在菜单中显示的权限
- #获取所有菜单
- #放置在session
- MenuHelper(request,username)
- return redirect('/index.html')
- else:
- return redirect('/login.html')
三:权限类生成(进行权限和菜单的业务处理)
- class MenuHelper(object):
- def __init__(self,request,username):
- #当前请求的request
- self.request = request
- #当前用户名
- self.username = username
- #获取当前url
- self.current_url = request.path_info
- #获取当前用户的所有权限
- self.permission2action_dict = {} #{'url':["操作列表"],}
- #菜单的叶子节点,即:菜单的最后一层应该(含有权限url)显示的权限,对应上面的permission2action_dict
- self.menu_leaf_list = []
- #获取所有菜单对象
- self.menu_list = []
- #初始化数据,将数据放入session中
- self.session_data()
- #注:只进行数据处理(数据最后是基础类型),不进行业务逻辑(目标就是将数据放在session中)
- def session_data(self):
- #()先在session中查看数据是否已经存在
- permission_dict = self.request.session.get("permission_info")
- if permission_dict:
- self.permission2action_dict = permission_dict['permission2action_dict']
- self.menu_leaf_list = permission_dict['menu_leaf_list']
- self.menu_list = permission_dict['menu_list']
- return
- #获取所有角色
- r_list = models.Role.objects.filter(user2role__u__username=self.username).all()
- #获取角色下的所有权限操作,存放方式{'url':["操作列表"],}便于查找 --> 例如 {'user.html':['get','post'],}
- p2a_list = models.Permission2Action.objects.filter(permission2action2role__r__in=r_list)
- #权限操作去重,使用集合去重
- p2a_list = set(p2a_list)
- #(1)循环权限操作列表,将其变为{'user.html':['get','post'],}格式,然后加入self.permission2action_dict
- for p2a in p2a_list:
- # print(p2a.p.url)
- if self.permission2action_dict.get(p2a.p.url) == None:
- self.permission2action_dict[p2a.p.url] = []
- self.permission2action_dict[p2a.p.url].append(p2a.a.code)
- #上面是用户拥有的所有权限,用于权限校验,下面这个是显示在菜单最后一层的权限(也只有最后一层才会有url权限)
- #()获取菜单的叶子节点,即:菜单的最后一层应该显示的权限
- self.menu_leaf_list = list(
- models.Permission2Action.objects. \
- filter(permission2action2role__r__in=r_list).exclude(p__menu__isnull=True). \
- values('p_id','p__url','p__caption','p__menu').distinct()
- )
- #()获取所有的菜单全部,(根据上面的菜单叶子节点,以及下面的所有菜单,进行比较,我们可以获取到所有应该显示的菜单)
- self.menu_list = list(models.Menu.objects.values('id','caption','parent_id'))
- #()将上面获取的数据,放入session中
- self.request.session['permission_info'] = {
- 'permission2action_dict':self.permission2action_dict,
- 'menu_leaf_list':self.menu_leaf_list,
- 'menu_list':self.menu_list,
- }
- #生成菜单树形结构(包括其他数据)
- def menu_data_list(self):
- menu_leaf_dict = {}
- #形式
- # {
- # '父id':['子节点','子节点',],
- # '父id':['子节点','子节点',]
- # }
- open_leaf_parent_id = None
- #(1)归并所有叶子节点
- for item in self.menu_leaf_list:
- item = {
- 'id':item['p_id'],
- 'url':item['p__url'],
- 'caption':item['p__caption'],
- 'parent_id':item['p__menu'], #对应的是菜单id,可以看出,每个叶子节点都是挂在菜单节点下面,我们只需获取菜单的树形结构,将权限叶子节点挂载上去就可以
- 'child':[],
- 'status':True, #是否显示
- 'open':False #是否展开
- }
- if item['parent_id'] in menu_leaf_dict:
- menu_leaf_dict[item['parent_id']].append(item)
- else:
- menu_leaf_dict[item['parent_id']] = [item,]
- if re.match(item['url'],self.current_url): #若是当前访问的url,则打开
- item['open'] = True
- open_leaf_parent_id = item['parent_id']
- #()获取所有菜单字典
- menu_dict = {}
- #形式也是
- # {
- # '菜单id':'对应数据处理的字典',
- # '菜单id': '对应数据处理的字典',
- # '菜单id': '对应数据处理的字典',
- # }
- for item in self.menu_list:
- item['child'] = []
- item['status'] = False #是否显示,只有拥有权限的菜单,才会展示给用户,其他的不会显示
- item['open'] = False #和权限叶子节点一致,展开就是一级一级显示,其他闭合
- menu_dict[item['id']] = item
- #根据上面的全部菜单和归并后的叶子节点一起获取我们真正需要的菜单
- #(3)将叶子节点添加到菜单中
- for k,v in menu_leaf_dict.items():
- menu_dict[k]['child'] = v #为菜单挂载上权限叶子节点
- parent_id = k
- while parent_id: #当权限子节点存在,则其父级会向上全部显示
- menu_dict[parent_id]['status'] = True
- parent_id = menu_dict[parent_id]['parent_id']
- #(4)将菜单中已经选中的菜单标记为展开(一级一级展开)
- while open_leaf_parent_id:
- menu_dict[open_leaf_parent_id]['open'] = True
- open_leaf_parent_id = menu_dict[open_leaf_parent_id]['parent_id']
- #()对所有菜单,进行树形结构生成,不需要考虑其他的因素(例如是否是叶子节点,是否有权限)
- #我们只需要判断状态status是否为True,然后筛选即可
- result = []
- for row in menu_dict.values(): #所有菜单进行树形排序
- if not row['parent_id']:
- result.append(row) # 注意:基础-->列表赋值的时候默认是浅拷贝,所以无论是是么时候添加到result中,后面的操作对于result数据也是有效d的
- else:
- menu_dict[row['parent_id']]['child'].append(row)
- #(6)返回树形结构
- return result
- #获取子菜单列表的子菜单列表(递归模式)
- def menu_content(self,child_list):
- response = ""
- # 菜单模板HTML
- tpl = """
- <div class="item %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['open']:
- 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_tree(self):
- response = ""
- # 菜单模板HTML
- tpl = """
- <div class="item %s">
- <div class="title">%s</div>
- <div class="content">%s</div>
- </div>
- """
- for row in self.menu_data_list(): #获取函数返回的树形结构,进行HTML处理,这里全是根目录菜单
- if not row['status']: #对于不需要显示的,不做处理
- continue
- active = ""
- if row['open']: #对于展开的,我们要设置其状态为active
- active = "active"
- title = row['caption']
- #获取其子代的HTML,放在content中
- content = self.menu_content(row['child']) #默认子代是列表
- response += tpl % (active,title,content)
- return response
- def actions(self):
- '''
- 检测当前用户是否对当前url有权限访问,并获取对当前url有什么权限
- :return:
- '''
- action_list = []
- #当前数据中保存的权限是{'user.html':['get','post'],}格式,在self.permission2action_dict中
- for k,v in self.permission2action_dict.items():
- if re.match(k,self.current_url):
- action_list = v
- break
- return action_list
四:生成装饰器(用于用户的验证,使用了上面类)
- #设置装饰器
- def permission(func):
- def inner(request,*args,**kwargs):
- user_info = request.session.get('user_info')
- if not user_info:
- return redirect("/login.html")
- obj = MenuHelper(request,user_info['username'])
- action_list = obj.actions()
- if not action_list:
- return HttpResponse("无权限访问")
- kwargs['menu_string'] = obj.menu_tree()
- kwargs['action_list'] = action_list
- return func(request,*args,**kwargs)
- return inner
五:装饰器使用
- @permission
- def index(request,*args,**kwargs):
- acion_list = kwargs.get('action_list')
- menu_string = kwargs.get("menu_string")
- if str(request.method).lower() in acion_list:
- result = "数据,可以访问"
- else:
- result = "没有数据,无权限访问"
- return render(request,'index.html',{'menu_string':menu_string,'action_list':acion_list,'result':result})
六:退出业务
- def logout(request):
- request.session.clear()
- return redirect('/login.html')
七:前台模板,以及效果展示
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- .item{
- margin-left: 24px;
- }
- .item a{
- margin-left: 24px;
- }
- </style>
- </head>
- <body>
- <div>
- <span>菜单显示</span>
- {{ menu_string|safe }}
- </div>
- <div>
- <span>结果数据</span>
- {{ result }}
- </div>
- </body>
- </html>
python---权限管理和菜单生成的更多相关文章
- 基于RBAC模式的权限管理系统设计概要
很多人都知道以角色为基础的权限管理设计(RBAC),但是大部分人似懂非懂,不知道完整的权限管理系统都包括哪些内容. 在此以权限管理的使用场景来说明一下完整的权限管理内容. 一是鉴权管理,即权 ...
- winform快速开发平台 -> 通用权限管理之动态菜单
这几个月一直忙APP的项目,没来得及更新项目,想想该抽出时间整理一下开发思路,跟大家分享,同时也希望得到宝贵的建议. 先说一下我们的权限管理的的设计思路,首先一个企业信息化管理系统一定会用到权限管理, ...
- 【Python】django权限管理
参考:http://www.cnblogs.com/esperyong/ 参考:https://docs.djangoproject.com/en/1.8/topics/auth/default/#t ...
- 【Ecshop】后台菜单与权限管理
主要php文件: 1,admin/includes/inc_menu.php ECSHOP管理中心菜单数组--配置菜单组及URL 2,languages/zh_cn/admin/common.php ...
- 练习:python 操作Mysql 实现登录验证 用户权限管理
python 操作Mysql 实现登录验证 用户权限管理
- 基于吉日嘎底层架构的Web端权限管理操作演示-菜单模块管理
按照顺序,这一篇介绍菜单模块管理,主要演示如下操作: 新增.修改.锁定.解锁.删除.撤销删除 排序 角色成员管理 用户成员管理 导出菜单模块数据 也许你会问,你在这自吹自擂,你这个BS的权限管理有啥缺 ...
- 仿SiteMap实现Asp.net 网站的菜单和权限管理
在Asp.net中,SiteMap用于站点导航,可以与Menu等控件一起使用实现网站的菜单和权限管理.但是SiteMap提供的方法都是只读的,无法再运行时修改(菜单)导航文件,需要手动修改配置web. ...
- Python 学习 第十篇 CMDB用户权限管理
Python 学习 第十篇 CMDB用户权限管理 2016-10-10 16:29:17 标签: python 版权声明:原创作品,谢绝转载!否则将追究法律责任. 不管是什么系统,用户权限都是至关重要 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) ...
随机推荐
- TCP 连接管理
实验代码和内容:https://github.com/ZCplayground/Understanding-Unix-Linux-Programming/tree/master/11.socket 明 ...
- apache +PHP多版本 切换的问题
在开发中切换php版本的时候出错 经过2小时的日子排查终于找到是因为切换版本后加载的php7ts.dll模块还是原来版本的,因此保pid file 错误 解决方法 PHPIniDir "H: ...
- Python基础【3】:Python中的深浅拷贝解析
深浅拷贝 在研究Python的深浅拷贝区别前需要先弄清楚以下的一些基础概念: 变量--引用--对象(可变对象,不可变对象) 切片(序列化对象)--拷贝(深拷贝,浅拷贝) 我是铺垫~ 一.[变量--引用 ...
- mybatis中@Param的使用
@Param:当映射器方法需要多个参数时,这个注解可以被用于:给映射器方法中的每个参数来取一个名字.否则,多参数将会以它们的顺序位置和SQL语句中的表达式进行映射,这是默认的. 语法要求:若使用 ...
- Common Substrings POJ - 3415(长度不小于k的公共子串的个数)
题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1 sa[i] < len1 和 sa[i-1] < ...
- 迭代解析JSON简单实例
由于项目中遇到了这个问题,所以在这里记录一下. 比如:请求到的JSON串: { "msg":"数据获取成功", "success":true ...
- Android Support WorkManager使用详解
使用WorkManager调度任务 WorkManager是一个库, 用以将工作入队, 当该工作的约束条件得到满足之后, WorkManager保证它的执行. WorkManager允许观测工作的状态 ...
- SHA1WithRSA签名 规范化标准签名
#region CerRsaSignature 根据私钥签名 /// <summary> /// 根据私钥串签名 /// </summary> /// <param na ...
- 【uoj121】 NOI2013—向量内积
http://uoj.ac/problem/121 (题目链接) 题意 给出${n}$个${d}$维向量,问是否有两个不同的向量的内积是${k}$的倍数. Solution 又卡了一上午常数,我弃了T ...
- Kerberos无约束委派的攻击和防御
0x00 前言简介 当Active Directory首次与Windows 2000 Server一起发布时,Microsoft就提供了一种简单的机制来支持用户通过Kerberos对Web服务器进行身 ...