Django-rbac权限

1、注册应用rbac

2、设计表

权限表

角色表

用户表

不同角色有不同的权限,给每个用户分配不同的角色(一个用户可以有多个角色)

3、数据注入

将数据注入在rbac中封装成一个函数

4、权限认证是在中间件进行的

我们将中间件也写在组件内

在settings注册中间件:

5、settings中配置我们经常用到的变量

6、配置路由分发

6、菜单栏权限分配

创建菜单表

菜单与权限一对多关联

表结构如下:

菜单表:

权限表:

给这些url分配菜单,哪个url属于哪些菜单,后面的pid是为了表示从属关系,

7、权限注入

登录成功后将用户的所有权限和权限中是菜单的信息保存在session中

取出当前登录用户拥有的所有权限,根据权限表中的menu_id判断哪些权限属于一级菜单;

构建菜单的数据结构,方便前端渲染;

所有权限保存在一个变量中保存到session中;

菜单权限保存在一个变量中保存到session中;

 # 判断是否是一级菜单
        if item["menu_id"]:
            # 如果menu_id在权限列表中,表示已经存在二级菜单,
            if item["menu_id"] in permisson_is_menu_dict:
                permisson_is_menu_dict[item["menu_id"]]["children"].append({
                    "pk":item["pk"],"title": item["title"], "url": item["url"]
                })
            else:
                # 设计菜单栏数据结构(方便前端渲染)
                permisson_is_menu_dict[item["menu_id"]] = {
                    "title": item["menu__title"],
                    "icon": item["menu__icon"],
                    "children": [
                        { "pk":item["pk"],"title": item["title"], "url": item["url"]},
                    ]
                }

8、权限认证

权限认证在中间件中,因为每访问一个网页都需要走一遍中间件

取出保存在session中的当前登录用户的权限数据与当前请求的url进行匹配

# 权限认证
for item in request.session[settings.PERMISSION_LIST]:
    res = "^%s$"%item
    ret = re.search(res,request.path)
    if ret:
        return None
return HttpResponse("您的权限不够不能访问该页面!!!")

9、菜单栏渲染

通过自定义标签给页面渲染菜单

取出我们在登陆后保存在session中的菜单数据

import re
from django import template
from django.conf import settings
register = template.Library()

# 自定义标签
@register.inclusion_tag("result.html")
def create_label(request):
    menu_dict = request.session.get(settings.PERMISSION_MENU_DICT)
    for key, item in menu_dict.items():
        # 默认给二级标签添加隐藏样式
        item["class"] = "hide"
        for child in item["children"]:
            # if re.match("^{}$".format(child["url"]), request.path):
            # 当前访问路径的pid如果等于它二级菜单的id证明他俩是属于同一个一级菜单,
            # 如果是属于同一个一级菜单,我们就让这个二级菜单一直显示,并给它添加选中样式;
            # request.show_id是当前请求路径的id值,我们在中间件中将当前请求路径的id封装在了request中
            if request.show_id == child["pk"]:
                item["class"] = ""
                child["class"] = "active"
                break
    return  {"menu_dict" :menu_dict }
原文地址:https://www.cnblogs.com/songzhixue/p/11068961.html