django自定义rbac权限组件(二级菜单)
一、目录结构
二、表结构设计
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权限组件(二级菜单)的更多相关文章
- django权限之二级菜单
遗漏知识点 1.构建表结构时,谁被关联谁就是主表,在层级删除的时候,删除子表的时候,主表不会被删除,反之删除主表的话,字表也会被删除, 使用related_name=None 反向查询,起名用的 ...
- rbac权限组件整合到实际项目的全过程详述
rbac简介 项目的GitHub地址 欢迎Download&Fork&Star:https://github.com/Wanghongw/CombineRbac 另外,本文只简单介绍一 ...
- CRM项目之RBAC权限组件-day26
写在前面 上课第26天,打卡: 世间安得双全法 不负如来不负卿 s17day26 CRM项目 项目概要:XX公司CRM - 权限管理,公共组件,app ***** - 熟悉增删改查,Low *** - ...
- RABC权限控制(二级菜单实现)
目前大部分系统由于用户体验,基本上菜单不会做的很深,以二级菜单为例,做了一个简单的权限控制实现,可精确到按钮级别(基于django),下面具体看看实现 1.表结构的设计 无论开发什么都需要先梳理清楚需 ...
- yii2 rbac权限控制之菜单menu详细教程
作者:白狼 出处:http://www.manks.top/article/yii2_rbac_menu本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...
- 1、rbac权限组件-初识, 中间件校验1
1.权限组件rbac 1.什么是权限 1 项目与应用 2 什么是权限? 一个包含正则表达式url就是一个权限 who what how ---------->True or Flase 2.版本 ...
- django中的构造字典(二级菜单,评论树,购物车)
1.构造父子结构: 1.1需求样式 客户列表 customer_list /customer/list/ -----> 添加客户 customer_add /customer/add/ ---- ...
- Django REST framework —— 权限组件源码分析
在上一篇文章中我们已经分析了认证组件源码,我们再来看看权限组件的源码,权限组件相对容易,因为只需要返回True 和False即可 代码 class ShoppingCarView(ViewSetMix ...
- Django实现Rbac权限管理
权限管理 权限管理是根据不同的用户有相应的权限功能,通常用到的权限管理理念Rbac. Rbac 基于角色的权限访问控制(Role-Based Access Control)作为传统访问控制(自主访问, ...
随机推荐
- 第十三章 Spring消息(待续)
···············
- Java之匿名内部类和包装类
匿名内部类 作用: 假如某个类只使用一次,则可以使用匿名内部类,无需再新建该类 我们上下代码: package com.learn.chap03.sec16; /** * 定义接口 */ public ...
- Java微信公众平台开发(十二)--微信用户信息的获取
转自:http://www.cuiyongzhi.com/post/56.html 前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信 ...
- 判定元素是否刚插入到DOM树
上接<这篇博文>,其应用于avalon的if绑定.如果一个节点还没有插入DOM树,那么avalon将延时对它进行扫描渲染,直到它再次插入到DOM树为止.由于CSS3 keyframe动画的 ...
- 面试题:Java程序员最常用的20%技术 已看1
首先常用api(String,StringBuffer/StringBuilder等) 1.集合类,线程类 2.Servlet(很少用纯粹的servlet写,但你要懂,因为很多框架都是基于servle ...
- Entity Framework Tutorial Basics(43):Download Sample Project
Download Sample Project: Download sample project for basic Entity Framework tutorials. Sample projec ...
- Entity Framework Tutorial Basics(42):Colored Entity
Colored Entity in Entity Framework 5.0 You can change the color of an entity in the designer so that ...
- Oracle数据库管理
一.Oracle 的(资源限制)概要文件 为了控制系统资源的使用, 可以利用资源限制概要文件. 资源限制概要文件是 Oracle 安全策略的重要组成部分, 利用资源限制概要文件可以对数据库用户进行基本 ...
- MVC值提供组件ValueProvider的继承关系
MVC请求过程中中各组件调用顺序:值提供组件(IValueProvider)->模型绑定组件(IModelBinder)->模型验证组件 值提供组件接口 public interface ...
- What is the AppData folder?
Applies to Windows 8.1, Windows RT 8.1 The AppData folder contains app settings, files, and data spe ...