2、rbac组件 后台布局模板,权限按钮,菜单,可拔插,路径重定向
1、后台布局管理
https://www.cnblogs.com/venicid/p/7772742.html#_label0
1、通用模板
overflow: auto; //在a和b模板中进行切换 a 模板 :左侧菜单跟随滚动条
b模板 左侧以及上不动 ****
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title> <style type="text/css">
.header {
width: 100%;
height: 60px;
background-color: #369;
} .right {
float: right;
} .left {
float: left;
} .menu {
position: absolute;
top: 60px;
left: 0;
bottom: 0;
background-color: gainsboro;
width: 20%;
} .content {
position: absolute;
top: 60px;
right: 0;
bottom: 0;
background-color: mediumpurple;
width: 80%; overflow: auto; //在a和b模板中进行切换
} </style>
</head>
<body> <div class="header"></div> <div class="container">
<div class="menu left">
1111
</div> <div class="content right">222
{% block content %} {% endblock %}
</div> </div> </body>
</html>
2、模板继承
users.html / roles.html 继承自 base.html
users.html
{% extends 'base.html' %} {% block con %}
<h4>用户列表</h4>
{% for user in user_list %}
<p>{{ user }}</p>
{% endfor %} {% endblock con%}
2、权限按钮控制:简单控制
用户权限不同,按钮显示就不同!
登录成功后,就已经注册了session
request.session['permission_list'] = permission_list permission_list = request.session.get('permission_list')
简单控制:
{% if "users/add" in permissions_list%}
3、修改表结构
BUT: 不好,不想让 if "/users/add/" 写死,会有 "/roles/add/" 情况,不健壮!怎么办? 不应该根据表名,去判断!!
权限不同,按钮显示就不同 如何做呢?
上面问题的解决办法:
为了扩展,
# 把两条线 合成一个线
/users/..
/roles/...
1、admin显示字段
注意:list_display = []
2、添加action,group字段
注意点:
加了一个权限组表,
将每张表的增删改查,划到一个组里面!
无论多复杂的,最终一定是对数据库的(增删改查) 修改表结构,重新处理中间件,登录页面:
目的:全是为了按钮的粒度,同一个模板,同一个视图,
显示不同的数据,权限
from django.db import models # Create your models here. class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
roles = models.ManyToManyField(to='Role') def __str__(self):
return self.name class Role(models.Model):
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(to="Permission") def __str__(self):
return self.title class Permission(models.Model):
title = models.CharField(max_length=32)
url = models.CharField(max_length=32)
action = models.CharField(max_length=32, default="") group = models.ForeignKey(to="PermissionGroup", on_delete=True)
def __str__(self):
return self.title class PermissionGroup(models.Model):
title = models.CharField(max_length=32 )
def __str__(self):
return self.title
4、重构数据结构
1、登录验证
2、构建permission_dict
3.登录之后,重写 initial_session(user,request)
就是:
# 在session中注册权限列表 用户权限
# request.session['permission_list'] = permission_list 不应该是list 而是dict # 在session中注册权限字典
request.session['permission_dict'] = permission_dict
注意点:
permission = user.roles.all().values('permission__url', 'permission__group_id', 'permission__action').distinct()
对数据的处理,以组为键
{1: {'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)/', '/users/edit/(\\d+)/'],
'actions': ['list', 'add', 'delete', 'edit']},
2: {'urls': ['/roles/'],
'actions': ['list']}}
# -*- coding: utf-8 -*-
# @Time : 2018/08/11 0011 9:24
# @Author : Venicid def initial_session(request,user):
# 方案2
permissions = user.roles.all().values("permissions__url", "permissions__group_id","permissions__action").distinct()
print(permissions)
# <QuerySet [{'permissions__url': '/users/',
# 'permissions__group_id': 1,
# 'permissions__action': 'list'}]> permission_dict = {}
for item in permissions:
gid = item.get("permissions__group_id")
if not gid in permission_dict:
permission_dict[gid] = {
"urls":[item["permissions__url"],],
"actions":[item["permissions__action"],]
}
else:
permission_dict[gid]["urls"].append(item["permissions__url"])
permission_dict[gid]["actions"].append(item["permissions__action"]) print(permission_dict) # {1: {'urls': ['/users/'], 'actions': ['list']}}
request.session["permission_dict"] = permission_dict # 方案1:
"""
permissions = user.roles.all().values("permissions__url").distinct() permission_list = []
for item in permissions:
permission_list.append(item['permissions__url']) print(permission_list) # ['/users/', '/users/add', '/users/delete/(\\d+)', '/users/edit/(\\d+)'] request.session["permission_list"] = permission_list
""" """
values : for role in user.roles.all(): # <QuerySet [<Role: 保洁>, <Role: 销售>]>
temp.append({
"title":role.title,
"permissions_url":role.permissions.all()
}) # <QuerySet [{'title': '保洁', 'permissions__url': '/users/'},
# {'title': '销售', 'permissions__url': '/users/'},
# {'title': '销售', 'permissions__url': '/users/add'}]> """
5、限制权限粒度
1、中间件校验权限:
# 注意:妙 !!
request.actions = item["actions"]
# -*- coding: utf-8 -*-
# @Time : 2018/08/11 0011 9:04
# @Author : Venicid import re from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect class ValidPermission(MiddlewareMixin):
def process_request(self, request): # 当前访问路径
current_path = request.path_info # 1、检验是否属于白名单 白名单,不需要任何权限的url
# 正则匹配
valid_url_list = ['/login/', '/reg/', '/admin/.*']
for valid_url in valid_url_list:
ret = re.match(valid_url, current_path) if ret:
return None # 2、校验是否登录
user_id = request.session.get("user_id")
if not user_id:
return redirect('/login/') # 3、校验权限2 permission_dict = request.session.get("permission_dict", {})
# {1: {'urls': ['/users/'], 'actions': ['list']}} for item in permission_dict.values():
urls = item["urls"]
for reg in urls:
reg = "^%s$" % reg
ret = re.match(reg, current_path)
if ret:
print("actions",item["actions"])
request.actions = item["actions"]
return None
return HttpResponse("没有访问权限") # 3、校验权限1
"""
permission_list = request.session.get("permission_list",[])
print(permission_list) flag = False
for permission in permission_list:
permission = "^%s$" % permission
# print(111111111,permission)
# print(current_path)
ret = re.match(permission, current_path)
if ret:
flag = True
break if not flag:
return HttpResponse("没有访问权限")
return None
"""
rbac中间件
模板层,权限按钮控制
2:用类来实现!!
from django.shortcuts import render, HttpResponse # Create your views here. from rbac.models import *
from rbac.service.perssions import * class Per(object):
def __init__(self, actions):
self.actions = actions
def add(self):
return "add" in self.actions
def delete(self):
return "delete" in self.actions
def edit(self):
return "edit" in self.actions
def list(self):
return "list" in self.actions def users(request):
user_list = User.objects.all()
permission_list = request.session.get("permission_list") # 查询当前登录人的名字
id = request.session.get("user_id")
user = User.objects.filter(id=id).first()
print(user) per = Per(request.actions) return render(request, "users.html", locals()) def add_user(request):
return HttpResponse('add user') def delete_user(request, id):
return HttpResponse('delete_user') def edit_user(request, id):
return HttpResponse('edit_user') def roles(request):
role_list = Role.objects.all() per = Per(request.actions)
print(request.actions)
return render(request, "roles.html", locals()) def login(request):
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd") user = User.objects.filter(name=user, pwd=pwd).first()
if user:
############## 在session中注册用户
request.session['user_id'] = user.pk ############# 在session中注册权限list
initial_session(request, user) return HttpResponse("登录成功") return render(request, 'login.html', locals())
View
3、效果
不同的用户,具有不同的权限,
权限不同,显示的按钮就不同!!
6、权限不同,菜单显示不同
只有查看,有必要放到菜单栏!
即:action == list 放到 菜单栏中
1.用户登录后,在initial_session中,注册菜单权限
注意:permission__group__title 还可以这样用,跨了3张表!!
# -*- coding: utf-8 -*-
# @Time : 2018/08/11 0011 9:24
# @Author : Venicid def initial_session(request,user):
# 方案2
permissions = user.roles.all().values("permissions__url", "permissions__group_id","permissions__action").distinct()
print(permissions)
# <QuerySet [{'permissions__url': '/users/',
# 'permissions__group_id': 1,
# 'permissions__action': 'list'}]> permission_dict = {}
for item in permissions:
gid = item.get("permissions__group_id")
if not gid in permission_dict:
permission_dict[gid] = {
"urls":[item["permissions__url"],],
"actions":[item["permissions__action"],]
}
else:
permission_dict[gid]["urls"].append(item["permissions__url"])
permission_dict[gid]["actions"].append(item["permissions__action"]) print(permission_dict) # {1: {'urls': ['/users/'], 'actions': ['list']}}
request.session["permission_dict"] = permission_dict # 注册菜单权限
permissions = user.roles.all().values("permissions__url", "permissions__action", "permissions__group__title").distinct() print(permissions)
menu_permission_list = []
for item in permissions:
if item["permissions__action"] == "list":
menu_permission_list.append((item["permissions__url"], item["permissions__group__title"])) print(menu_permission_list) # [('/users/', '用户组'), ('/roles/', '角色组')]
request.session["menu_permission_list"] = menu_permission_list # 方案1:
"""
permissions = user.roles.all().values("permissions__url").distinct() permission_list = []
for item in permissions:
permission_list.append(item['permissions__url']) print(permission_list) # ['/users/', '/users/add', '/users/delete/(\\d+)', '/users/edit/(\\d+)'] request.session["permission_list"] = permission_list
""" """
values : for role in user.roles.all(): # <QuerySet [<Role: 保洁>, <Role: 销售>]>
temp.append({
"title":role.title,
"permissions_url":role.permissions.all()
}) # <QuerySet [{'title': '保洁', 'permissions__url': '/users/'},
# {'title': '销售', 'permissions__url': '/users/'},
# {'title': '销售', 'permissions__url': '/users/add'}]> """
2、menu
可以实现,菜单显示!但是不行,为什么? 因为模板继承,只继承样式,不继承数据!所有需要用到 自定义标签(inclusion_tag)
3、自定义标签(inclusion_tag)
# -*- coding: utf-8 -*-
# @Time : 2018/08/12 0012 16:11
# @Author : Venicid from django import template register = template.Library() @register.inclusion_tag("rbac/menu.html")
def get_menu(request):
# 获取当前用户可以放到菜单栏中的权限
menu_permission_list = request.session.get("menu_permission_list") print(menu_permission_list) return {"menu_permission_list":menu_permission_list}
+
7、可拔插配置:包...建在哪个App
属于权限的就建在rbac的APP里,因为rpac最后是可插拔的组件!! users.html / roles.html / base.html / menu.html
是和权限相关的,所以应该放在 rbac/templates/... 方便以后copy走!! djangod的render去渲染 .html 时,先到项目的 templates 下找,找不到,再到App下 templates 下找,
最后找不到,才报错!!
如果多个App的templates 下的.html重名怎么办? django 会根据注册的顺序显示!
解决办法:
项目/rbac/templates/rbac/xxx.html 这时调用:
return render(request, 'rbac/users.html', locals()) 注意:
templates 或者 templatetag 注意多个app下面 的文件名 有可能都会重名!!
办法:就是 eg:/rbac/templates/rbac/xxx.html 或者不起重名
注意:
如果 base.html 在项目下有,在App下有,先找项目下的,找不到才找App
全局可以覆盖局部的!!
8、路径自动添加
知识点:路径自动添加问题:
http://127.0.0.1:8010/users
http://127.0.0.1:8010/users/ 浏览器发请求:
django 发现之后,发了一个重定向的 url 加了一个 /
所有才能匹配上:
path('users/', views.users), 如何让django不给浏览器发重定向,不加 /
配置:
APPEND_SLASH = False APPEND_SLASH = True # 默认为 True ajax 也是,django会默认的加 / 发重定向
1、django浏览器重定向
2、APPEND_SLASH = False
ajax 也是,django会默认的加 / 发重定向
9、github代码
https://github.com/venicid/rbac
2、rbac组件 后台布局模板,权限按钮,菜单,可拔插,路径重定向的更多相关文章
- rbac组件权限按钮,菜单,可拔插
1.通用模板 overflow: auto; //在a和b模板中进行切换 a 模板 :左侧菜单跟随滚动条 b模板 左侧以及上不动 **** <!DOCTYPE html> <h ...
- 3YAdmin-专注通用权限控制与表单的后台管理系统模板
3YAdmin基于React+Antd构建.GitHub搜索React+Antd+Admin出来的结果没有上百也有几十个,为什么还要写这个东西呢? 一个后台管理系统的核心我认为应该是权限控制,表单以及 ...
- python 全栈开发,Day108(客户管理之权限控制,客户管理之动态"一级"菜单,其他应用使用rbac组件,django static文件的引入方式)
一.客户管理之权限控制 昨天的作业,有很多不完善的地方 下载代码,基本实现权限验证 https://github.com/987334176/luffy_permission/archive/v1.2 ...
- Sweetalert模态对话框与Swiper轮播插件、Bootstrap样式组件、AdminLTE后台管理模板地址
Sweetalert纯JS模态对话框插件地址:http://mishengqiang.com/sweetalert/ AdminLTE后台管理模板系统地址(基于Bootstrap):https://a ...
- rbac组件之权限初始化(五)
当用户登陆后,根据用户的角色要为用户生成对应的权限菜单,此时需要将登陆的用户信息获取且获取角色信息,从数据库中获取菜单以及权限信息,并且存入session中. 1.权限流程 第一次请求的页面是登陆页面 ...
- Vue3+ElementPlus的一套开源前台+后台管理模板
Vue-Element-Faster 基于最新版vue.js 3.x与element-plus2.x实现的一套前台展示系统.后台管理系统模板,自带权限管理模块. API接口基于SpringBoot2. ...
- day72 关于rbac组件的小部分面试题
rbac的权限组件 基于角色的权限控制 1.什么是权限? url代表的就是一个权限 2.如何实现权限的控制? 表结构 以我们讲的课的内容为例 菜单表: - title 标题 - icon 图标 ...
- SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 后端篇(五): 数据表设计、使用 jwt、redis、sms 工具类完善注册登录逻辑
(1) 相关博文地址: SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 前端篇(一):搭建基本环境:https://www.cnblogs.com/l-y-h/p ...
- 基于vite2+electron12后台管理模板|Electron后台框架系统
前一溜时间有给大家分享一个 electron+vite跨端短视频 项目.这次分享的是vite2.x和electron实现跨平台后台框架,支持国际化多语言配置.导航菜单+树形菜单两种路由菜单模式.展开/ ...
随机推荐
- Semaphore-信号灯机制
我们创建一个可扩展大小的线程池,并且需要在线程池内同时让有限数目的线程并发运行时,就需要用到Semaphore(信号灯机制),Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目 ...
- 关于sys CPU usage 100%问题的分析
最近一个客户抱怨他的核心EBS数据库出现性能问题.这是一个10.2.0.3的数据库,运行在Red Hat Enterprise Linux Server release 5.5 (Linux x86- ...
- [UI] 精美UI界面欣赏[6]
精美UI界面欣赏[6]
- linux如何查看端口被何进程占用
1.lsof -i:端口号 2.netstat -tunlp|grep 端口号 都可以查看指定端口被哪个进程占用的情况 工具/原料 linux,windows xshell 方法/步骤 [ ...
- Celery学习---Celery 与django结合实现计划任务功能
项目的目录结构: 项目前提: 安装并启动Redis 安装Django和Celery的定时任务插件 安装方法一: pip直接安装[安装了pip的前提下] omc@omc-virtual-machine: ...
- CSS学习摘要-数值和单位及颜色
在CSS中,值的类型有很多种,一些很常见,一些你却几乎没怎么遇到过.我们不会在这篇文档中面面俱到地描述他们,而只是这些对于掌握CSS可能最有用处的这些.本文将会涉及如下CSS的值: 数值: 长度值,用 ...
- 解决qpidd服务安装不上的问题
前几天对一个文件夹命名,忘记了qpidd的路径在这个文件夹的下面,导致后来qpidd用不了. 并且有打开计算机-管理-服务时,看到Advanced MessageQueuing Protocol 未启 ...
- .NET Core 控制台项目中的Nuget打包类库及引用
由于使用的是MAC版本的VSCode,所以全部是通过dotnet命令来完成的. 1.dotnet new lib 创建类库项目: 2.编辑项目根目录下的.csproj文件,添加版本号(建议): < ...
- 51nod 1589 移数博弈【桶排序+链表】
1589 移数博弈 基准时间限制:1 秒 空间限制:262144 KB 分值: 80 难度:5级算法题 小A和小B在玩一个游戏. 他们拥有一个数列. 小A在该数列中选择出最大的那个数,然后移出该数 ...
- python中pandas里面的dataframe数据的筛选小结
pandas大家用的都很多,像我这种用的不够熟练,也不够多的就只能做做笔记,尽量留下点东西吧. 筛选行: a. 按照列的条件筛选 df = pandas.DataFrame(...) # suppos ...