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%} 

这样完全足够满足开发的需求,并且没有BUG,但是这样做并不严谨,需要更改数据表结构。

3、修改表结构

不想让 if "/users/add/" 写死,会有 "/roles/add/" 情况,不健壮!怎么办?      不应该根据表名,去判断!! 
权限不同,按钮显示就不同 如何做呢?    
上面问题的解决办法:
  为了扩展,
  # 把两条线 合成一个线
  /users/..
   /roles/...

1、admin显示字段

注意:list_display = []

2、添加action,group字段

注意点:
加了一个权限组表,
将每张表的增删改查,划到一个组里面!
无论多复杂的,最终一定是对数据库的(增删改查) 修改表结构,重新处理中间件,登录页面:
目的:全是为了按钮的粒度,同一个模板,同一个视图,
显示不同的数据,权限

新的数据表:

models.py

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("PermissionGroup",default=1,on_delete=models.CASCADE)
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()

对数据的处理,以组为键

print(permissions)  #把下列结构构建成一个permission_dict
'''
permissions=[
{'permissions__url': '/users/', 'permissions__group_id': 1, 'permissions__action': 'list'}, {'permissions__url': '/users/add/', 'permissions__group_id': 1, 'permissions__action': 'add'}, {'permissions__url': '/roles/', 'permissions__group_id': 2, 'permissions__action': 'list'}, {'permissions__url': '/users/delete/(\\d+)', 'permissions__group_id': 1, 'permissions__action': 'delete'}, {'permissions__url': 'users/edit/(\\d+)', 'permissions__group_id': 1, 'permissions__action': 'edit'}
] '''
{1: {'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)/', '/users/edit/(\\d+)/'],
'actions': ['list', 'add', 'delete', 'edit']},
2: {'urls': ['/roles/'],
'actions': ['list']}}

def initial_session(user,request):
#方案一
# permissions = user.roles.all().values("permissions__url").distinct()
# print(permissions)
# permission_list = []
# for item in permissions:
# print("items",item)
# permission_list.append(item["permissions__url"])
# print(permission_list)
# request.session["permission_list"] = permission_list #方案二
permissions = user.roles.all().values("permissions__url","permissions__group_id","permissions__action").distinct()
print(permissions)
permission_dict = {}
temp = []
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)
request.session["permission_dict"]=permission_dict #注册菜单权限
permissions = user.roles.all().values("permissions__url", "permissions__group__title", "permissions__action").distinct()
menu_permission_list=[]
for item in permissions:
if item["permissions__action"] == "list":
menu_permission_list.append((item["permissions__url"],item["permissions__group__title"])) # print("permission",men_permission_list)
#注册到session中
request.session["menu_permission_list"]=menu_permission_list

5、限制权限粒度

1、中间件校验权限:

    # 注意:妙 !!
request.actions = item["actions"]

    

  

rbac.py方案二

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 # 检查是否属于白名单
valid_url_list=["/login/","/reg/","/admin/.*"] for valid_url in valid_url_list:
ret=re.match(valid_url,current_path)
if ret:
return None # 校验是否登录
user_id=request.session.get("user_id") if not user_id:
return redirect("/login/") #校验权限2
permission_dict=request.session.get("permission_dict",[])#加个列表防止空不可循环导致保存
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("没有访问权限!")
     #在中间件校验权限的过程中,匹配到哪儿成功了,把匹配到那里对应的actions取出来,放到request.actions中.

模板层,权限按钮控制

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张表!!

2、menu

可以实现,菜单显示!但是不行,为什么?

    因为模板继承,只继承样式,不继承数据!所有需要用到 自定义标签(inclusion_tag)

3、自定义标签(inclusion_tag)

my_tags.py

# Author:Jesi
# Time : 2018/9/17 13:44
from django import template
register=template.Library() @register.inclusion_tag("rbac/menu.html")
def get_menu(request,):
menu_permission_list=request.session["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
全局可以覆盖局部的!!

临时补充问题(与rbac无关):

 

路径自动添加

知识点:路径自动添加问题:
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会默认的加 / 发重定向

 

rbac组件权限按钮,菜单,可拔插的更多相关文章

  1. 2、rbac组件 后台布局模板,权限按钮,菜单,可拔插,路径重定向

    1.后台布局管理 https://www.cnblogs.com/venicid/p/7772742.html#_label0 1.通用模板 overflow: auto; //在a和b模板中进行切换 ...

  2. python 全栈开发,Day108(客户管理之权限控制,客户管理之动态"一级"菜单,其他应用使用rbac组件,django static文件的引入方式)

    一.客户管理之权限控制 昨天的作业,有很多不完善的地方 下载代码,基本实现权限验证 https://github.com/987334176/luffy_permission/archive/v1.2 ...

  3. rbac之 权限粒度控制到按钮级别

    rbac之 权限粒度控制到按钮级别:  这里的意思就是 如果当前用户,没有这个权限. 那么这个相对应的这个按钮的权限, 就不应该展示.看都不能给看到. 思路: 为每一个权限,设置一个别名.  这里是这 ...

  4. 应用rbac组件 动态生成一级菜单

    动态生成一级菜单 改表结构 需要知道是否是菜单\icon\名称权限表 +字段: is_menu = models.BooleanField(max_length=32,verbose_name='是否 ...

  5. 第二百零八节,jQuery EasyUI,SplitButton(分割按钮菜单)组件

    jQuery EasyUI,SplitButton(分割按钮)组件 学习要点: 1.加载方式 2.属性列表 3.方法列表 本节课重点了解 EasyUI 中 SplitButton(分割按钮)组件的使用 ...

  6. JavaEE权限管理系统的搭建(六)--------使用拦截器实现菜单URL的跳转权限验证和页面的三级菜单权限按钮显示

    本小结讲解,点击菜单进行页面跳转,看下图,点击管理员列表后会被认证拦截器首先拦截,验证用户是否登录,如果登录就放行,紧接着会被权限验证拦截器再次拦截,拦截的时候,会根据URL地址上找到对应的方法,然后 ...

  7. rbac组件之权限初始化(五)

    当用户登陆后,根据用户的角色要为用户生成对应的权限菜单,此时需要将登陆的用户信息获取且获取角色信息,从数据库中获取菜单以及权限信息,并且存入session中. 1.权限流程 第一次请求的页面是登陆页面 ...

  8. rbac组件之菜单操作(三)

    菜单包括菜单列表,菜单列表不仅将菜单列出来,而且将每个菜单下的权限也列出来.菜单的添加.删除.修改. urls.py ... re_path(r'^menus/list/$', MenuView.as ...

  9. rbac组件引用

    一. 批量操作思路 # 待新增 路由系统中有,但是数据库中还没有 路由系统的集合 - 数据库中权限集合 # 待更新 路由系统中有,数据库中也有, 只是更改了一些信息 路由系统的集合 & 数据库 ...

随机推荐

  1. Windows Server 2016-管理站点复制(一)

    可以使用Active Directory站点和服务管理单元来管理实现站点间复制拓扑的特定于站点的对象.这些对象存储在Active Directory域服务 (AD DS) 的站点容器中.同一个站点内的 ...

  2. python--私有属性--私有方法

    Class 定义类 def 初始化方法(形参) 属性1 属性2   私有属性(属性之前加--) def  方法1() print() 属性和方法定义好以后,在创建对象 对象=类名(“”) print( ...

  3. ELK收集tomcat状态日志

    1.先查看之前的状态日志输出格式:在logs/catalina.out这个文件中 最上面的日志格式我们可能不太习惯使用,所以能输出下面的格式是最好的,当然需要我们自定义日志格式,接下来看看如何修改 2 ...

  4. python——函数之生成器

    1 生成器函数的含义    生成器是一个返回可以迭代对象的函数,它是一个特殊的迭代器,但迭代器的抽象层级更高且比较复杂需要实现很多方法.相较迭代器而言,生成器简单使用. 2 生成器的创建方式 2.1 ...

  5. 新安装 Ubuntu 系统设置root用户密码!谨此纪念自己踩过的坑!

    Ubuntu 在安装过程中创建的用户为普通用户,而root 用户密码该如何设置呢? 执行以下命令即可: sudo passwd root 提示你输入普通用户密码,然后设置root用户的密码!这样,就更 ...

  6. March 10th, 2018 Week 10th Saturday

    All good things must come to an end. 好景无常. Love is when the other person's happiness is more importa ...

  7. Java strictfp

    strictfp关键字 用于强制Java中的浮点计算(float或double)的精度符合IEEE 754标准. 不使用strictfp:浮点精度取决于目标平台的硬件,即CPU的浮点处理能力. 使用s ...

  8. ES5-ES6-ES7_字符串扩展—模板字符串

    includes(), startsWith(), endsWith() 传统上,JavaScript只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中.ES6又提供了三种新方法 ...

  9. 设计模式のFlyweight(享元模式)----结构模式

    一.产生背景 享元模式:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件.通常物件中的部分状态是可以分享.常见做 ...

  10. C#事件の事件聚合器

    事件聚合器用于集中管理事件的订阅(Subscribe)和处理(Handle),要使用事件聚合器,首先要理解:事件(event)本质上是一个类. 传统的+=和-=不足: 1.管理很麻烦:2.不方便扩展. ...