一、模板继承

知识点:

users.html / roles.html 继承自 base.html
滑动时,固定
position: fixed;top:60px;bottom:0;left:0;width:200px;
overflow: auto; base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>base</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style type="text/css">
*{padding: 0;margin: 0;}
.header{width: 100%; height: 60px;background-color: #336699;}
.menu{background-color: bisque; position: fixed; top:60px;bottom: 0;left: 0; width: 200px;}
.content{ position: fixed;top: 60px;bottom: 0; right: 0; left: 200px;overflow: auto;padding: 20px;} </style> </head>
<body> <div class="header">
<p>{{ user.name }}</p>
</div> <div class="container">
<div class="menu">
menu
</div> <div class="content">
{% block con %} {% endblock con%}
</div>
</div> </body>
</html>

users.html

{% extends 'base.html' %}

{% block con %}
<h4>用户列表</h4>
{% for user in user_list %}
<p>{{ user }}</p>
{% endfor %} {% endblock con%}

二、table

知识点:

{% for user in user_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ user.name }}</td>
<td>
{% for role in user.roles.all %}
  {{ role.title }}
{% endfor %}
</td>
<td>
<a href="" class="btn btn-danger">删除</a>
<a href="" class="btn btn-warning">编辑</a>
</td>
</tr>
{% endfor %}

users.html

{% extends 'base.html' %}

{% block con %}
<h4>用户列表</h4>
<a href="" class="btn btn-primary">添加</a>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>角色</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for user in user_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ user.name }}</td>
<td>
{% for role in user.roles.all %}
{{ role.title }}
{% endfor %}
</td>
<td>
<a href="" class="btn btn-danger">删除</a>
<a href="" class="btn btn-warning">编辑</a>
</td>
</tr>
{% endfor %} </tbody> </table> {% endblock con%}

三、权限不同(按钮 。。。)

用户权限不同,按钮显示就不同! 
登录成功后,就已经注册了session
request.session['permission_list'] = permission_list permission_list = request.session.get('permission_list') 0.
{% if "/users/add/" in permission_list %}
<a href="/users/add/" class="btn btn-primary">添加</a>
{% endif %} {% if '/users/delete/(\d+)/' in permission_list %}
<a href="/users/delete/{{ user.pk }}/" class="btn btn-danger">删除</a>
{% endif %} BUT: 不好,不想让 if "/users/add/" 写死,会有 "/roles/add/" 情况,不健壮!怎么办?
不应该根据表名,去判断!!
权限不同,按钮显示就不同 如何做呢?    
上面问题的解决办法:
  为了扩展,
  # 把两条线 合成一个线
  /users/..
   /roles/...
1.修改表结构 
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=True) def __str__(self):
return self.title class PermissionGroup(models.Model):
title = models.CharField(max_length=32) def __str__(self):
return self.title makemigrations
migrate

注意点:

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

models.py

from django.db import models

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)
permission = 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=True) def __str__(self):
return self.title class PermissionGroup(models.Model):
title = models.CharField(max_length=32) def __str__(self):
return self.title
2.admin 修改

注意:list_display = []

admin.py
from django.contrib import admin
from .models import * class PerConfig(admin.ModelAdmin):
list_display = ['title','url','group','action'] admin.site.register(User)
admin.site.register(Role)
admin.site.register(Permission,PerConfig)
admin.site.register(PermissionGroup)

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']}}
permission.py
# -*- coding:utf-8 -*-

def initial_session(user, request):
# 方案一
# permission = user.roles.all().values('permission__url').distinct()
# # print(permission)
# # 去重后的 所有权限!! 将权限 存在 session 中!!
# # <QuerySet [{'permission__url': '/users/'}, {'permission__url': '/users/add'}]>
#
# permission_list = []
# for item in permission:
# permission_list.append(item['permission__url'])
#
# print(permission_list) # ['/users/', '/users/add']
#
# # 在session中注册权限列表 用户权限
# request.session['permission_list'] = permission_list # 方案二
permission = user.roles.all().values('permission__url', 'permission__group_id', 'permission__action').distinct() print('permission:', permission) # permission: <QuerySet [
# {'permission__url': '/users/',
# 'permission__group_id': 1,
# 'permission__action': 'list'}, # {'permission__url': '/users/add/',
# 'permission__group_id': 1,
# 'permission__action': 'add'}, # {'permission__url': '/users/delete/(\\d+)/',
# 'permission__group_id': 1,
# 'permission__action': 'delete'}, # {'permission__url': '/users/edit/(\\d+)/',
# 'permission__group_id': 1,
# 'permission__action': 'edit'}]> # {'permission__url': 'roles/',
# 'permission__group_id': 2,
# 'permission__action': 'list'}]> # 处理数据 : 以组为键
"""
1:{
"url":['/users/','/users/add','/users/delete/(\\d+)/','/users/edit/(\\d+)']
"action":['list','add','delete','edit']
} 2:{
"url":['/roles/']
"action":['list']
} """ permission_dict = {}
for item in permission:
gid = item.get('permission__group_id')
url = item.get('permission__url')
action = item.get('permission__action') if not gid in permission_dict.keys():
permission_dict[gid] = {
"urls": [url, ],
"actions": [action, ]
} else:
permission_dict[gid]['urls'].append(url)
permission_dict[gid]['actions'].append(action) print(permission_dict)
"""
{1: {'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)/', '/users/edit/(\\d+)/'],
'actions': ['list', 'add', 'delete', 'edit']},
2: {'urls': ['/roles/'],
'actions': ['list']}}
""" # 注册session
# # 在session中注册权限字典 用户权限 request.session['permission_dict'] = permission_dict
4.重写中间件
校验权限 # 注意:妙 !!
request.actions = item["actions"] rbac.py
# -*- coding:utf-8 -*-
from django.shortcuts import HttpResponse, render, redirect
from django.utils.deprecation import MiddlewareMixin
import re class ValidPermission(MiddlewareMixin): def process_request(self,request): current_path = request.path_info # 白名单,不需要任何权限的url
valid_url_list = ['/login/', '/reg/', '/admin/.*'] for valid_url in valid_url_list:
ret = re.match(valid_url, current_path)
if ret:
return # 校验是否登录
user_id = request.session.get('user_id')
if not user_id:
return redirect('/login/') # # 校验权限 1
# permission_list = request.session.get('permission_list',[])
#
# flag = False
# for permission in permission_list:
# # ['/users/', '/users/add/', '/users/edit/(\\d+)/', '/users/delete/(\\d+)/']
# # 需要 ^ $ 限定!!
# permission = "^%s$" % permission
#
# ret = re.match(permission, current_path)
# if ret:
# flag = True
# break
#
# if not flag:
# return HttpResponse('无访问权限!') # 校验权限 2 permission_dict
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("action", item['actions']) # 注意:妙 !!
request.actions = item["actions"] return return HttpResponse('无权访问') """
permission_dict: {1: {'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)/', '/users/edit/(\\d+)/'],
'actions': ['list', 'add', 'delete', 'edit']},
2: {'urls': ['/roles/'],
'actions': ['list']}} """
5.重写users()视图,以及users.html

    1.也可以实现:
{% if "add" in request.actions %}
<a href="/users/add/" class="btn btn-primary">添加</a>
{% endif %} BUT: 还可以更好:用类来实现!! {% if per.add %}
<a href="/users/add/" class="btn btn-primary">添加</a>
{% endif %} {% if per.delete %}
<a href="" class="btn btn-danger">删除</a>
{% endif %}
-------
per = Per(request.actions) 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 views.py
from django.shortcuts import render,HttpResponse,redirect
import re from rbac.models import *
from rbac.service.permission import initial_session 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() user_id = request.session.get('user_id')
user = User.objects.filter(id=user_id).first() per = Per(request.actions) return render(request,'users.html',locals())

users.html

{% extends 'base.html' %}

{% block con %}
<h4>用户列表</h4> {# {% if "/users/add/" in permission_list %}#}
{# {% if "add" in request.actions %}#}
{% if per.add %}
<a href="/users/add/" class="btn btn-primary">添加</a>
{% endif %} <table class="table table-bordered table-striped">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>角色</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for user in user_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ user.name }}</td>
<td>
{% for role in user.roles.all %}
{{ role.title }}
{% endfor %}
</td>
<td>
{% if per.delete %}
<a href="" class="btn btn-danger">删除</a>
{% endif %}
{% if per.edit %}
<a href="" class="btn btn-warning">编辑</a>
{% endif %}
</td>
</tr>
{% endfor %} </tbody> </table> {% endblock con%}

四、效果

不同的用户,具有不同的权限,

权限不同,显示的按钮就不同!!


权限粒度控制

简单控制:
{% if "users/add" in permissions_list%} 摆脱表控制 更改数据库结构
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)
def __str__(self):return self.title class PermissionGroup(models.Model):
title = models.CharField(max_length=32) def __str__(self): return self.title 登录验证:
permissions = user.roles.all().values("permissions__url","permissions__group_id","permissions__action").distinct() 构建permission_dict permissions:
[ {'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'}
] permission_dict
{ 1: {
'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)', 'users/edit/(\\d+)'],
'actions': ['list', 'add', 'delete', 'edit']}, 2: {
'urls': ['/roles/'],
'actions': ['list']} } 中间件校验权限:
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("没有访问权限!") 思考:
菜单权限显示

笔记

五、权限不同(菜单。。。)

权限不同,菜单栏不同

只有查看,有必要放到菜单栏!
即:action == list 放到 菜单栏中 1.用户登录后,在initial_session中,注册菜单权限 注意:permission__group__title 还可以这样用,跨了3张表!! permissions = user.roles.all().values('permission__url', 'permission__action',
'permission__group__title').distinct() menu_permission_list = []
for item in permissions:
if item['permission__action'] == 'list':
menu_permission_list.append((item['permission__url'], item['permission__group__title'])) print(menu_permission_list)
# [('/users/', '用户管理'), ('/roles/', '角色管理')] request.session['menu_permission_list'] = menu_permission_list
2.menu
menu_permission_list = request.session.get('menu_permission_list') base.html
{% for item in menu_permission_list %}
<p class="menu_btn"><a href="{{ item.0 }}">{{ item.1 }}</a></p>
{% endfor %} 可以实现,菜单显示!但是不行,为什么? 因为模板继承,只继承样式,不继承数据!所有需要用到 自定义标签(inclusion_tag) 3.自定义标签(inclusion_tag)
rbac/templatetags/my_tags.py
from django import template
register = template.Library() @register.inclusion_tag('menu.html')
def get_menu(request):
# 获取当前用户,应该放到菜单栏的权限
menu_permission_list = request.session.get('menu_permission_list') return {'menu_permission_list':menu_permission_list} menu.html:
<div>
{% for item in menu_permission_list %}
<p class="menu_btn"><a href="{{ item.0 }}">{{ item.1 }}</a></p>
{% endfor %} </div> base.html
{% load my_tags %}
<div class="menu">
{% get_menu request %}
</div>
4.包...建在哪个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
全局可以覆盖局部的!!

六、效果

用户的权限不同,

显示的菜单栏,就不同,

按钮也不同

七、路径自动添加

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

八、rbac_code

原始版

https://github.com/alice-bj/rbac_pro_0

rbac - 界面、权限的更多相关文章

  1. RBAC角色权限控制

    RBAC角色权限控制 1. user (用户表) *  用户的基本信息(mid:用户信息id  如图) 2. node (节点表) * 页面(模块\控制器\方法) 3. role_node(角色.节点 ...

  2. ThinkPHP框架下基于RBAC的权限控制模式详解

    这几天因为要做一个项目,需要可以对Web应用中通用功能进行封装,其中一个很重要的涉及到了对用户.角色和权限部分的灵活管理.所以基于TP框架自己封装了一个对操作权限和菜单权限进行灵活配置的可控制模式. ...

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

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

  4. 百万年薪python之路 -- RBAC角色权限设计

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成"用 ...

  5. Java生鲜电商平台-RBAC系统权限的设计与架构

    Java生鲜电商平台-RBAC系统权限的设计与架构 说明:根据上面的需求描述以及对需求的分析,我们得知通常的一个中小型系统对于权限系统所需实现的功能以及非功能性的需求,在下面我们将根据需求从技术角度上 ...

  6. 基于thinkphp3.2.3开发的CMS内容管理系统(二)- Rbac用户权限

    基于thinkphp3.2.3开发的CMS内容管理系统 thinkphp版本:3.2.3 功能: --分类栏目管理 --文章管理 --商品管理 --用户管理 --角色管理 --权限管理 --友情链接管 ...

  7. 基于RBAC实现权限管理

    基于RBAC实现权限管理 技术栈:SpringBoot.SpringMVC RBAC RBAC数据库表 主体 编号 账号 密码 001 admin 123456 资源 编号 资源名称 访问路径 001 ...

  8. Spring Security实现基于RBAC的权限表达式动态访问控制

    昨天有个粉丝加了我,问我如何实现类似shiro的资源权限表达式的访问控制.我以前有一个小框架用的就是shiro,权限控制就用了资源权限表达式,所以这个东西对我不陌生,但是在Spring Securit ...

  9. rbac——界面、权限

    一.模板继承 知识点: users.html / roles.html 继承自 base.html 页面滚动时,固定 .menu { background-color: bisque; positio ...

随机推荐

  1. 如何研究某个gene的ceRNA 网络

    研究人员针对 PTEN 这个关键的抑癌基因,来探究调控该基因表达的ceRNA 网络: 分析策略: 1)预测能调控该基因的miRNAs 通过miRanda 软件预测和实验验证相结合的方式,挑选出 miR ...

  2. 一个窗口里包含一个iframe,点击iframe内的submit按钮,返回的视图总是显示在iframe中,我想要的效果是点击按钮后返回的视图是在浏览器窗口中...?asp.net mvc 的action中,不用js怎么实现??????????

    Content("<script type='text/javascript'>parent.location.href = '" + url + "';&l ...

  3. is_file,is_dir,file_exists

    is_file()和file_exists()效率比较,结果当文件存在时,is_file函数比file_exists函数速度快14倍,当文件不存在时,两者速度相当.同理,当文件目录存在时,is_dir ...

  4. js openwindow

    进入许多网站时,有弹出式小窗口,它们五花八门,使我们捉摸不透下面就来介绍用JS制作9种制作弹出小窗口: 1.最基本的弹出窗口代码         其实代码非常简单:         < SCRI ...

  5. Http Digest认证协议

    转自:http://blog.csdn.net/htjoy1202/article/details/7067287 其认证的基本框架为挑战认证的结构,如下图所示: 1.客户端希望取到服务器上的某个资源 ...

  6. 【MongoDB】数组长度查询

    db.groupedInfo.count({'surveyInfo.surveyAndUserID.0':{$exists:1}})

  7. bootstrap 标签页tab切换js(含报错原因)

    booststrap 标签页的tab切换,相信大家已经都很熟悉了,在boot官网示例以及其他网站已经很多罗列相关代码的了,这里就不赘述了.这里主要贴下让boot标签页默认显示哪个标签页的js. 主要留 ...

  8. c++ 类数据成员的定义、声明

    C++为类中提供类成员的初始化列表类对象的构造顺序是这样的:1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员2.进入构造函数后在构造函数中执行一般计算  1.类里面的任何成员变量在定义时是不 ...

  9. python2.0 s12 day2

    s12 day2 视频每节的内容 05 python s12 day2 python编码   1.第一句python代码 python 执行代码的过程 文件读到内存 分析内容 编译字节码  转换机器码 ...

  10. osgEarth中的StringUtils头文件中有很多关于字符串的操作