Django RBAC权限管理设计过程详解


Posted in Python onAugust 06, 2019

一.权限简介

1. 问:为什么程序需要权限控制?

答:生活中的权限限制,① 看灾难片电影《2012》中富人和权贵有权登上诺亚方舟,穷苦老百姓只有等着灾难的来临;② ?潘棵牵?忻挥邢牍??裁茨切┏さ闷?辽聿暮玫墓媚镌谀闵肀卟淮嬖谀兀恳蛭?星?撕推?凉媚锒际钦涔笙∮械模?∮械娜嗽谝黄鹜嫠:徒馑?髦肿耸啤6?悖?奕ㄓ涤兴?牵?荒茏约和孀约毫恕?br />

程序开发时的权限控制,对于不同用户使用系统时候就应该有不同的功能,如:

  • 普通员工
  • 部门主管
  • 总监
  • 总裁

所以,只要有不同角色的人员来使用系统,那么就肯定需要权限系统。

2. 问:为什么要开发权限组件?

答:假设你今年25岁,从今天开始写代码到80岁,每年写5个项目,那么你的一生就会写275个项目,保守估计其中应该有150+个都需要用到权限控制,为了以后不再重复的写代码,所以就开发一个权限组件以便之后55年的岁月中使用。 亲,不要太较真哦,你觉得程序员能到80岁么,哈哈哈哈哈哈哈

偷偷告诉你:老程序员开发速度快,其中一个原因是经验丰富,另外一个就是他自己保留了很多组件,新系统开发时,只需把组件拼凑起来基本就可以完成。

3. 问:web开发中权限指的是什么?

答:web程序是通过 url 的切换来查看不同的页面(功能),所以权限指的其实就是URL,对url控制就是对权限的控制。

结论:一个人有多少个权限就取决于他有多少个URL的访问权限。

二.权限表结构设计:第一版

问答环节中已得出权限就是URL的结论,那么就可以开始设计表结构了。

  • 一个用户可以有多个权限。
  • 一个权限可以分配给多个用户。

你设计的表结构大概会是这个样子:

Django RBAC权限管理设计过程详解

现在,此时此刻是不是觉得自己设计出的表结构棒棒哒!!!

But,无论是是否承认,你还是too young too native,因为老汉腚眼一看就有问题....

问题:假设 “maple”和“ffm” 这俩货都是老板,老板的权限一定是非常多。那么试想,如果给这俩货分配权限时需要在【用户权限关系表中】添加好多条数据。假设再次需要对老板的权限进行修改时,又需要在【用户权限关系表】中找到这俩人所有的数据进行更新,太他妈烦了吧!!! 类似的,如果给其他相同角色的人来分配权限时,必然会非常繁琐。

三.权限表结构设计:第二版

聪明机智的一定在上述的表述中看出了写门道,如果对用户进行角色的划分,然后对角色进行权限的分配,这不就迎刃而解了么。

  • 一个人可以有多个角色。
  • 一个角色可以有多个人。
  • 一个角色可以有多个权限。
  • 一个权限可以分配给多个角色。

表结构设计:

Django RBAC权限管理设计过程详解

这次调整之后,由原来的【基于用户的权限控制】转换成【基于角色的权限控制】,以后再进行分配权限时只需要给指定角色分配一次权限,给众多用户再次分配指定角色即可。

from django.db import models
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)

  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)
  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = 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)

  def __str__(self):
    return self.name

注意:现在的设计还不是最终版,但之后的设计都是在此版本基础上扩增的,为了让大家能够更好的理解,我们暂且再此基础上继续开发,直到遇到无法满足的情况,再进行整改。

四.客户管理之动态“一级”菜单

from django.db import models
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)
  icon = models.CharField(verbose_name='图标', max_length=32, null=True, blank=True, help_text='菜单才设置图标')
  is_menu = models.BooleanField(verbose_name='是否是菜单', default=False)

  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)

  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = 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)
  def __str__(self):
    return self.name

五.客户管理之动态“二级”菜单

from django.db import models
class Menu(models.Model):
  """
  菜单
  """
  title = models.CharField(verbose_name='菜单', max_length=32)
  icon = models.CharField(verbose_name='图标', max_length=32)
  def __str__(self):
    return self.title
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)
  menu = models.ForeignKey(verbose_name='菜单', to='Menu', null=True, blank=True, help_text='null表示非菜单')
  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)
  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = 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)
  def __str__(self):
    return self.name

六.客户管理之默认展开非菜单URL

from django.db import models
class Menu(models.Model):
  """
  菜单
  """
  title = models.CharField(verbose_name='菜单', max_length=32)
  icon = models.CharField(verbose_name='图标', max_length=32)
  def __str__(self):
    return self.title
class Permission(models.Model):
  """
  权限表
  """
  title = models.CharField(verbose_name='标题', max_length=32)
  url = models.CharField(verbose_name='含正则的URL', max_length=128)

  pid = models.ForeignKey(verbose_name='默认选中权限', to='Permission', related_name='ps', null=True, blank=True,
              help_text="对于无法作为菜单的URL,可以为其选择一个可以作为菜单的权限,那么访问时,则默认选中此权限",
              limit_choices_to={'menu__isnull': False})  
  menu = models.ForeignKey(verbose_name='菜单', to='Menu', null=True, blank=True, help_text='null表示非菜单')
  def __str__(self):
    return self.title
class Role(models.Model):
  """
  角色
  """
  title = models.CharField(verbose_name='角色名称', max_length=32)
  permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)
  def __str__(self):
    return self.title
class UserInfo(models.Model):
  """
  用户表
  """
  name = 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)
  def __str__(self):
    return self.name

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
布同 Python中文问题解决方法(总结了多位前人经验,初学者必看)
Mar 13 Python
Python3使用requests登录人人影视网站的方法
May 11 Python
python中is与双等于号“==”的区别示例详解
Nov 21 Python
python监控键盘输入实例代码
Feb 09 Python
python文本数据相似度的度量
Mar 12 Python
Pandas读取MySQL数据到DataFrame的方法
Jul 25 Python
python进阶之多线程对同一个全局变量的处理方法
Nov 09 Python
Python 分享10个PyCharm技巧
Jul 13 Python
selenium 多窗口切换的实现(windows)
Jan 18 Python
django-crontab实现服务端的定时任务的示例代码
Feb 17 Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
Aug 07 Python
python中如何打包用户自定义模块
Sep 23 Python
python虚拟环境完美部署教程
Aug 06 #Python
python批量图片处理简单示例
Aug 06 #Python
Python实用库 PrettyTable 学习笔记
Aug 06 #Python
浅谈django2.0 ForeignKey参数的变化
Aug 06 #Python
Python中调用其他程序的方式详解
Aug 06 #Python
运用PyTorch动手搭建一个共享单车预测器
Aug 06 #Python
基于python实现自动化办公学习笔记(CSV、word、Excel、PPT)
Aug 06 #Python
You might like
php定时计划任务与fsockopen持续进程实例
2014/05/23 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
js动态创建表格,删除行列的小例子
2013/07/20 Javascript
js控制表单操作的常用代码小结
2013/08/15 Javascript
jquery模拟SELECT下拉框取值效果
2013/10/23 Javascript
js确认删除对话框适用于a标签及submit
2014/07/10 Javascript
node.js超时timeout详解
2014/11/26 Javascript
第三章之Bootstrap 表格与按钮功能
2016/04/25 Javascript
浅谈js图片前端预览之filereader和window.URL.createObjectURL
2016/06/30 Javascript
数组Array的排序sort方法
2017/02/17 Javascript
深入理解node.js http模块
2018/01/24 Javascript
Vue-Router模式和钩子的用法
2018/02/28 Javascript
详解Angular中通过$location获取地址栏的参数
2018/08/02 Javascript
Vue Cli3 创建项目的方法步骤
2018/10/15 Javascript
vue计算属性computed、事件、监听器watch的使用讲解
2019/01/21 Javascript
JS使用数组实现的队列功能示例
2019/03/04 Javascript
基于原生js实现判断元素是否有指定class名
2020/07/11 Javascript
vue 中的动态传参和query传参操作
2020/11/09 Javascript
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
2020/12/14 NodeJs
Python采用Django制作简易的知乎日报API
2016/08/03 Python
Python线程创建和终止实例代码
2018/01/20 Python
python 拼接文件路径的方法
2018/10/23 Python
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
2019/04/09 Python
Django中的静态文件管理过程解析
2019/08/01 Python
Django ORM 自定义 char 类型字段解析
2019/08/09 Python
通过 Python 和 OpenCV 实现目标数量监控
2020/01/05 Python
python tkinter实现下载进度条及抖音视频去水印原理
2021/02/07 Python
Clarks英国官方网站:全球领军鞋履品牌
2016/11/26 全球购物
关于青春的演讲稿800字
2014/08/22 职场文书
公司新人试用期自我评价
2014/09/17 职场文书
2014向国旗敬礼网上签名活动总结
2014/09/27 职场文书
2015年销售内勤工作总结
2015/04/27 职场文书
庆七一活动简报
2015/07/20 职场文书
结婚纪念日感言
2015/08/01 职场文书
服务行业标语口号
2015/12/26 职场文书
maven依赖的version声明控制方式
2022/01/18 Java/Android