一、目录结构

二、表结构设计

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. python利用scapy模块写一个TCP路由追踪和扫描存活IP的脚本

    前言: 没有前言 0x01 from scapy.all import * import sys from socket import * import os from threading impor ...

  2. Python Twisted系列教程13:使用Deferred新功能实现新客户端

    作者:dave@http://krondo.com/deferred-all-the-way-down/  译者:杨晓伟(采用意译) 你可以从这里从头阅读这个系列. 介绍 回忆下第10部分中的客户端5 ...

  3. Python not readable

    try: with open('data.txt','w') as f: for each_line in f: print(each_line)except OSError as reason: p ...

  4. Apple Ad Hoc

    Apple Ad Hoc 发布测试 App只能通过Ad Hoc分享给绑定我们账号的设备上,所以至是一百台 1.官网member Center创建Ad Hoc证书 2.在官网下载Ad Hoc证书到mac ...

  5. 在VS13上编译通过的代码放在12上编译-错误:l __dtoui3 referenced in function _event_debug_map_HT_GROW

    在VS13上编译通过的代码放在12上编译 遇到错误:l __dtoui3 referenced in function _event_debug_map_HT_GROW 1>------ 已启动 ...

  6. MVC,MVP 和 MVVM 的详解

    一.MVC MVC模式的意思是,软件可以分成三个部分. 视图(View):用户界面. 控制器(Controller):业务逻辑 模型(Model):数据保存 各部分之间的通信方式如下. View 传送 ...

  7. 11-EasyNetQ之多态发布和订阅

    你能够订阅一个接口,然后发布基于这个接口的实现. 让我们看下一个示例.我有一个接口IAnimal和两个实现Cat和Dog: public interface IAnimal { string Name ...

  8. 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 5 Octave Tutorial—5.5 控制语句: for, while, if 语句

    5.5 控制语句: for, while, if 语句 参考视频: 5 - 5 - Control Statements_ for, while, if statements (13 min).mkv ...

  9. 安装 Windows Service

    1.打开 VS 命令行窗口 2. installutil /u  service文件路径  (卸载原有服务) 3, installutil /i  service 文件路径 (安装服务)

  10. 【bzoj2947】[Poi2000]促销

    2947: [Poi2000]促销 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 181  Solved: 120[Submit][Status][D ...