一、目录结构

二、表结构设计

model.py

from django.db import models

# Create your models here.

class Menu(models.Model):
"""菜单表 一级菜单"""
title = models.CharField(max_length=32)
icon = models.CharField(max_length=64, null=True, blank=True, verbose_name='图标') def __str__(self):
return self.title class Permission(models.Model):
"""
权限表
可以做二级菜单的权限 menu 关联 菜单表
不可以做菜单的权限 menu=null
"""
url = models.CharField(max_length=32, verbose_name='权限')
title = models.CharField(max_length=32, verbose_name='标题')
menu = models.ForeignKey("Menu",null=True, blank=True, verbose_name="所属菜单",on_delete=models.CASCADE) class Meta:
# 这个选项是指定,模型的复数形式是什么,比如:
# verbose_name_plural = "学校"
# 如果不指定Django会自动在模型名称后加一个’s’
verbose_name_plural = '权限表'
verbose_name = '权限' def __str__(self):
return self.title class Role(models.Model):
"""
角色表
"""
name = models.CharField(max_length=32, verbose_name='名称')
permissions = models.ManyToManyField('Permission', verbose_name='角色拥有的权限',blank=True) def __str__(self):
return self.name class User(models.Model):
"""
用户表
"""
name = models.CharField(max_length=32, verbose_name='名称')
password = models.CharField(max_length=32, verbose_name='密码')
roles = models.ManyToManyField('Role', verbose_name='用户拥有的角色',blank=True) def __str__(self):
return self.name

三、权限信息初始化

用户登陆成功后保留权限信息与菜单信息

service.permission.py

from django.conf import settings

def init_permisson(request, obj):
"""
权限信息的初识化
保存权限和菜单的信息
:param request:
:param obj:
:return:
"""
# 登陆成功,保存权限的信息(可能存在创建了角色没有分配权限,有的用户拥有多个角色权限重复的要去重.distinct())
ret = obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url',
'permissions__title',
'permissions__menu__title',
'permissions__menu__icon',
'permissions__menu_id'
).distinct() # 存放权限信息
permission_list = []
# 存放菜单信息
menu_dict = {}
for item in ret:
# 将所有的权限信息添加到permission_list
permission_list.append({'url': item['permissions__url']}) # 构造菜单的数据结构
menu_id = item.get('permissions__menu_id') # 表示当前的权限是不做菜单的权限
if not menu_id:
continue # 可以做菜单的权限
if menu_id not in menu_dict:
menu_dict[menu_id] = {
'title': item['permissions__title'], # 一级菜单标题
'icon': item['permissions__menu__icon'],
'children': [
{'title': item['permissions__menu__title'], 'url': item['permissions__url']},
]
}
else:
menu_dict[menu_id]['children'].append(
{'title': item['permissions__menu__title'], 'url': item['permissions__url']}) # print(menu_dict)
# 保留权限信息到session(因为session可以存到内存中,提高工作效率)中
request.session[settings.PERMISSION_SESSION_KEY] = permission_list # 保存菜单信息
request.session[settings.PERMISSION_MENU_KEY] = menu_dict

四、中间件中权限校验

菜单数据结构构造

注意构造菜单的数据结构,将查询出的元数据构造为分级的数据结构。

# 元数据
data = [{
'permissions__url': '/customer/list/',
'permissions__title': '客户列表',
'permissions__menu__title': '信息列表',
'permissions__menu__icon': 'fa-code-fork',
'permissions__menu_id': 1
},
{
'permissions__url': '/customer/list/',
'permissions__title': '用户列表',
'permissions__menu__title': '信息列表',
'permissions__menu__icon': 'fa-code-fork',
'permissions__menu_id': 1
}, {
'permissions__url': '/customer/add/',
'permissions__title': '增加客户',
'permissions__menu__title': None,
'permissions__menu__icon': None,
'permissions__menu_id': None
}, {
'permissions__url': '/customer/edit/(\\d+)/',
'permissions__title': '编辑客户',
'permissions__menu__title': None,
'permissions__menu__icon': None,
'permissions__menu_id': None
}]
# 目标数据
{
1:{
'title':'信息列表',
'icon':'fa-code-fork',
'children': [
{'title': '客户列表','url':'/customer/list/ },
{'title': '用户列表','url':'/customer/list/ }
] } }

middlewares.rbac.py

from django.conf import settings

def init_permisson(request, obj):
"""
权限信息的初识化
保存权限和菜单的信息
:param request:
:param obj:
:return:
"""
# 登陆成功,保存权限的信息(可能存在创建了角色没有分配权限,有的用户拥有多个角色权限重复的要去重.distinct())
ret = obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url',
'permissions__title',
'permissions__menu__title',
'permissions__menu__icon',
'permissions__menu_id'
).distinct() # 存放权限信息
permission_list = []
# 存放菜单信息
menu_dict = {}
for item in ret:
# 将所有的权限信息添加到permission_list
permission_list.append({'url': item['permissions__url']}) # 构造菜单的数据结构
menu_id = item.get('permissions__menu_id') # 表示当前的权限是不做菜单的权限
if not menu_id:
continue # 可以做菜单的权限
if menu_id not in menu_dict:
menu_dict[menu_id] = {
'title': item['permissions__title'], # 一级菜单标题
'icon': item['permissions__menu__icon'],
'children': [
{'title': item['permissions__menu__title'], 'url': item['permissions__url']},
]
}
else:
menu_dict[menu_id]['children'].append(
{'title': item['permissions__menu__title'], 'url': item['permissions__url']}) # print(menu_dict)
# 保留权限信息到session(因为session可以存到内存中,提高工作效率)中
request.session[settings.PERMISSION_SESSION_KEY] = permission_list # 保存菜单信息
request.session[settings.PERMISSION_MENU_KEY] = menu_dict

五、自定义inclusion_tag

用于定义html片段,实现动态数据传入。

文件包必须叫templatetags

templatetags.rbac.py

from django import template
from django.conf import settings
import re register = template.Library() @register.inclusion_tag('rbac/menu.html')
def menu(request):
# # 取到存在session 里的菜单权限信息信息(一级菜单时)
# menu_list = request.session.get(settings.PERMISSION_MENU_KEY)
#
# for item in menu_list:
# # 正则匹配当前路径
# if re.match('^{}$'.format(item['url']), request.path_info):
# # 添加一个点击样式
# item['class'] = 'active'
# break
# return {"menu_list": menu_list} # 二级菜单时
menu_dict = request.session.get(settings.PERMISSION_MENU_KEY) return {'menu_list': menu_dict.values()}

注意:为了不把数据写死,便于维护,存在session中的权限相关配置写在setting中

# session中保留权限key
PERMISSION_SESSION_KEY = 'permissions'
# 保留菜单信息key
PERMISSION_MENU_KEY = 'menus'
# 白名单
WHITE_LIST = [
r'^/login/$',
r'^/reg/$',
r'^/admin/.*',
]

在templates模板中应用菜单

html

   {% load rbac %}
{# <!--应用inclusion_tag('rbac/menu.html')-->#}
{% menu request %}

django自定义rbac权限组件(二级菜单)的更多相关文章

  1. django权限之二级菜单

    遗漏知识点 1.构建表结构时,谁被关联谁就是主表,在层级删除的时候,删除子表的时候,主表不会被删除,反之删除主表的话,字表也会被删除, 使用related_name=None   反向查询,起名用的 ...

  2. rbac权限组件整合到实际项目的全过程详述

    rbac简介 项目的GitHub地址 欢迎Download&Fork&Star:https://github.com/Wanghongw/CombineRbac 另外,本文只简单介绍一 ...

  3. CRM项目之RBAC权限组件-day26

    写在前面 上课第26天,打卡: 世间安得双全法 不负如来不负卿 s17day26 CRM项目 项目概要:XX公司CRM - 权限管理,公共组件,app ***** - 熟悉增删改查,Low *** - ...

  4. RABC权限控制(二级菜单实现)

    目前大部分系统由于用户体验,基本上菜单不会做的很深,以二级菜单为例,做了一个简单的权限控制实现,可精确到按钮级别(基于django),下面具体看看实现 1.表结构的设计 无论开发什么都需要先梳理清楚需 ...

  5. yii2 rbac权限控制之菜单menu详细教程

    作者:白狼 出处:http://www.manks.top/article/yii2_rbac_menu本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  6. 1、rbac权限组件-初识, 中间件校验1

    1.权限组件rbac 1.什么是权限 1 项目与应用 2 什么是权限? 一个包含正则表达式url就是一个权限 who what how ---------->True or Flase 2.版本 ...

  7. django中的构造字典(二级菜单,评论树,购物车)

    1.构造父子结构: 1.1需求样式 客户列表 customer_list /customer/list/ -----> 添加客户 customer_add /customer/add/ ---- ...

  8. Django REST framework —— 权限组件源码分析

    在上一篇文章中我们已经分析了认证组件源码,我们再来看看权限组件的源码,权限组件相对容易,因为只需要返回True 和False即可 代码 class ShoppingCarView(ViewSetMix ...

  9. Django实现Rbac权限管理

    权限管理 权限管理是根据不同的用户有相应的权限功能,通常用到的权限管理理念Rbac. Rbac 基于角色的权限访问控制(Role-Based Access Control)作为传统访问控制(自主访问, ...

随机推荐

  1. 9.solr学习速成之group

    Group与Facet的区别  facet的查询结果主要是分组信息:有什么分组,每个分组包括多少记录:但是分组中有哪些数据是不可知道的,只有进一步搜索.        group则类似于关系数据库的g ...

  2. MFC 文件I/O和串行化

    1.枚举所有文件夹(递归) void EnumerateFolders () { WIN32_FIND_DATA fd; HANDLE hFind = ::FindFirstFile (_T (&qu ...

  3. Windows 环境下Java调用CRF++详解

    1.步骤一览 2.步骤详情 2.1.环境准备 Swig(Simplified Wrapper and Interface Generator)下载,Windows操作系统直接解压即可使用 CRF++( ...

  4. Storm集群详细部署

    1.安装zookeeper 3.1下载zookeeper安装包, 建议下载3.4.5及以上的版本 http://www.apache.org/dyn/closer.cgi/zookeeper/ 3.2 ...

  5. Mycat实战之连续分片

    1 按照日期(天)分片: 从开始日期算起,按照天数来分片 例如,从2017-11-01,每10天一个分片且可以指定结束日期 注意事项:需要提前将分片规划好,建好,否则有可能日期超出实际配置分片数 1. ...

  6. s3c6410开发板LED驱动程序设计详细…

    2 下面来看看tiny6410关于LED的原理图如图(1)所示: 图1    LED原理图 3 LED实例,代码如下所示:(代码摘自\光盘4\实验代码\3-3-1\src\main.c) main.c ...

  7. java基础之JDBC五:批处理简单示例

    /** * 批处理 * 批处理跟事务不同 只是把一批sql放到一起执行 2条sql是可以一条执行成功 一条执行失败 是不可逆的 */ public class Test { public static ...

  8. 252. Meeting Rooms 区间会议室

    [抄题]: Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],.. ...

  9. 使用rpmbuild打包时不对文件进行strip操作

    使用rpmbuild打包时不对文件进行strip操作 摘自: https://www.ichenfu.com/2017/11/20/rpmbuild-not-strip/ By Chen Fu 发表于 ...

  10. getchar() getch() getche() gets() puts() scanf()的用法及区别

    getchar() putchar(ch) scanf()   头文件stdio.h getch() getche()   头文件conio.h gets() puts()    头文件stdio.h ...