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. monkey_recorder录制monkeyrunner脚本

    转载:monkey_recorder录制monkeyrunner脚本   1. 你必须有android sdk, sdk的tools文件家里有一个monkeyrunner.bat.2. 将如下内容拷贝 ...

  2. 某游戏公司(凯英网络)PHP开发工程师笔试题

  3. gcc5.4报错对‘std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()’未定义的引用

    我在编译ligra是遇到了这个问题,网上搜了一遍,发现是了原因https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/manual/using_dual_abi.ht ...

  4. Vue学习之路7-v-on指令学习之简单事件绑定

    前言 在JavaScript中任何一个DOM元素都有其自身存在的事件对象,事件对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置和鼠标按钮的状态等.事件通常与函数结合使用,函数不 ...

  5. PTA天梯 L3-007 天梯地图

    L3-007 天梯地图 题目: 本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线:一条是最短距离的路线.题目保证对任意的查询请求,地 ...

  6. MYSQL的binlog日志

    binlog 基本认识 MySQL的二进制日志以事件形式,记录了所有的DDL和DML(除了数据查询语句)语句,及语句执行消耗时间. MySQL的二进制日志是事务安全型的,是MySQL最重要的日志. b ...

  7. 在Python虚拟环境中安装scrapy

    虚拟环境安装scrapy 在虚拟环境中执行命令 (scrapyenv) E:\Python\Envs>pip install -i https://pypi.douban.com/simple/ ...

  8. JS(1) JavaScript 用法

    HTML 中的脚本必须位于 <script> 与 </script> 标签之间. 脚本可被放置在 HTML 页面的 <body> 和 <head> 部分 ...

  9. Python框架学习之Flask中的蓝图与单元测试

    因为Flask框架的集成度很低,随着Flask项目文件的增多,会导致不太好管理.但如果对一个项目进行模块化管理的,那样子管理起来就会特别方便.而在Flask中刚好就提供了这么一个特别好用的工具蓝图(B ...

  10. pg安装入门

    1.下载源码安装包 [root@test2019030517 ~]# wget https://ftp.postgresql.org/pub/source/v10.5/postgresql-10.5. ...