DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • BBS

  • 订单平台

  • CRM

    • rbac

      • 动态菜单
      • 菜单和权限管理
      • 权限分配
        • 权限分配
          • 实现思路
          • 第一步: 展现
          • 内存地址引用
          • 三级数据结构构建
          • 页面显示
          • 第二步: 筛选
          • 点击用户
          • 点击角色
          • 第三步: 分配
        • RBAC组件应用及完善
          • 准备工作
          • 用户表方案
          • 方案一
          • 方案二(推荐)
          • 开始修改
          • 业务逻辑开发
          • 注销和首页
          • 应用rbac
        • RBAC组件使用文档
    • stark

    • crm

  • flask+layui

  • django+layui

  • 供应链

  • 实战
  • CRM
  • rbac
DC
2024-03-12
目录

权限分配

权限分配本应在上一个md文档中阐述的, 奈何上篇文档文字篇幅已经有8千多字了, 所有 权限分配放到了该篇文档中! (´・Д・)」

# 权限分配

说白了, 就是给后台管理员一个页面, 让它可以给用户分配角色, 给角色分配权限!!

需深知: 是不支持直接给用户分配权限的, 需要通过角色!!

# 实现思路

我们分三步走

■ 展示: 在页面上展示用户、角色、权限信息

  • 用户、角色的信息很好呈现
  • 权限信息包含 一级菜单、二级菜单、以及二级菜单下的子权限, 需要构思适合的数据结构以便在页面上循环出来

■ 筛选: 默认选项! 简单来说,选择用户、角色时,页面上的默认选项 (checkbox是否被选中)

  • 点击用户后, 用户所拥有的角色和它所拥有的权限都会默认选中!
  • 点击角色后, 应该将该角色所拥有的权限信息都呈现出来!

■ 分配: 点击保存, 进行角色和权限的分配

  • 点击用户, 可给当前选中用户分配角色, 点击"保存"按钮进行保存!
  • 点击角色, 可给当前选中角色分配权限, 点击"保存"按钮进行保存!

# 第一步: 展现

目标: 在页面上展示 用户、角色、权限信息!!
重点在于理解 如何构建 权限信息的数据结构!! (呈现三级结构)

# 内存地址引用

先来回顾一个python的知识,借此明白两点:

△ 内存地址 △ 列表频繁查找的效率优化.

"""
第一点:对字典的引用. 
    <[字典是可变类型的数据]> for循环中的item本质是内存地址!!So,字典变了,引用该字典的所有地方都会同步变化!!
第二点:查找优化
    频繁的查找id为x的值在列表中是否存在!若每次都是列表查找,都会遍历一遍.
    但按照下述步骤将menu_list变成menu_dict去查找,会快很多,因为字典的查找是哈希!!
"""

menu_list = [
    {'id': 1, 'title': '客户管理'},
    {'id': 2, 'title': '账单管理'},
    {'id': 9, 'title': '权限管理'}
]

menu_dict = {}
for item in menu_list:
    item['children'] = []
    menu_dict[item["id"]] = item

menu_dict[2]['children'] = [11, 22]

"""
[
    {'id': 1, 'title': '客户管理', 'children': []}, 
    {'id': 2, 'title': '账单管理', 'children': [11, 22]}, 
    {'id': 9, 'title': '权限管理', 'children': []}]
"""
print(menu_list)
"""
{
    1: {'id': 1, 'title': '客户管理', 'children': []},
    2: {'id': 2, 'title': '账单管理', 'children': [11, 22]}, 
    9: {'id': 9, 'title': '权限管理', 'children': []}}
"""
print(menu_dict)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 三级数据结构构建

权限信息的数据结构构建

关键代码截图如下:

image-20240313164009927

让我瞅瞅, 权限信息的数据结构长这个样子!!! (*≧ω≦)

[
    {
        id: 1, 
        title: "客户管理", 
        children: []
    }, 
    {
        id: 2, 
        title: "账单管理", 
        children: []
    }, 
    {
        id: 9, 
        title: "权限管理", 
        children: [
            {
                id: 16, 
                title: "角色列表", 
                menu_id: 9, 
                children: [
                    {
                        id: 17, 
                        title: "添加角色", 
                        pid_id: 16
                    }, 
                    {
                        id: 18, 
                        title: "编辑角色", 
                        pid_id: 16
                    }, 
                    {
                        id: 19, 
                        title: "删除角色", 
                        pid_id: 16
                    }
                ]
            }, 
            {
                id: 38, 
                title: "分配列表", 
                menu_id: 9, 
                children: [ ]
            }
        ]
    }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 页面显示

ok, 将数据在页面上 循环展示出来!!

先来看看效果图:

image-20240314130306742

关键代码如下:

image-20240314132155496

# 第二步: 筛选

目标: 默认选项! 简单来说,选择用户、角色时,页面上的默认选项

# 点击用户

完成4个小需求.

先来看看效果:

40

需求1> 样式改变, 用于区分当前选中的是哪个用户.
需求2> 在第一个面板, 选择用户后, 第二个面板上应该出现 "保存" 按钮!! (用于后续为用户重新分配角色)
需求3> 在第一个面板, 选择用户后, 第二个面板应该自动将 当前选中用户所拥有的所有角色 都默认打上对勾!!
需求4> 在第一个面板, 选择用户后, 第三个面板应该自动将 当前选中用户所拥有的所有权限 都默认打上对勾!!

image-20240314140936736

这四个需求与"三级联动"那进行对比理解:

- 需求1、需求2, 跟前面那"三级联动"的实现逻辑是一样一样的!! ★
- 需求3,需求4 跟"三级联动"那换汤不换药
  只不过三级联动那是拿到所有的,在模版中for循环展示;我们这里拿到了,是看选项是否在这个里面,在的话加上选中样式 checked!!
  具体来说,根据user_id找到当前用户所分配角色的所有id,在前端循环时判断,若在,就在checkbox中加上checked. 所拥有权限的自动勾选同理.
1
2
3
4

Ps: 另外,截图中涉及到的多对多的正向查询语句, 在项目一开始实现"基本的权限控制"那就已经编写过啦!!原理一样.

# 点击角色

完成3个小需求. (与点击用户相比, 关键就在于权限面板展示权限的优先级做了点处理!!)

先来看看效果:

41

需求1> 点击角色, 样式改变, 用于区分当前选中的是哪个角色.
需求2> 在第二个面板, 选择角色后, 第三个面板上应该出现 "保存" 按钮!! (用于后续为角色重新分配权限)
需求3> 在第二个面板, 选择角色后, 第三个面板应该自动将 当前选中角色所拥有的所有角色 都默认打上对勾!!
★ 在权限面板的默认展示中, 选中角色的优先级比选中用户的优先级要高!!
1> 若选中了角色,哪怕还选中了用户,权限面板优先显示选中角色所拥有的权限.
2> 若没有选中角色,但选中了用户,权限面板显示当前选中用户所拥有的所有权限.

关键代码如下, 前端模版中的代码跟前面点击用户实现需求的代码逻辑一样, 不过多赘述..

image-20240314183659837

# 第三步: 分配

为用户分配角色, 为角色分配权限!!

先来看看效果

42

(¯﹃¯)思考一个问题:

不难想到,我们需要将角色面板和权限面板都用from标签包裹起来.
点击,type="submit"的保存按钮后,该表单中 选中的多选框 都会以 k-v 的形式传递到后端.
<!-- 若不给多选框设置value属性,勾选返回的都是on,设置后返回的是设置的值 -->
<input type="checkbox" name="roles" value="1"> CEO
<input type="checkbox" name="roles" value="2"> 总监
<input type="checkbox" name="roles" value="3"> 员工
后端通过 
  request.POST.get('表单的name属性值') -- 取最后一个
  request.POST.getlist('表单的name属性值') -- 可以接受全部数据 eg:多选框
  -- 然后将多对多的关系保存到数据库中!!
    
Q: 问题来了!! 后端咋知道前端提交的是哪个表单呢??
- 首先我们想到的是 <form method="post" action="?type=x1"> 在action中加上 ?type=x1 进行区分
  这个方法我们在 批量处理 页面使用过!! 但是该方法在这里不好使. why? 举个栗子:
  当前访问的是 http://127.0.0.1:8000/rbac/distribute/list/?uid=9&rid=2 选中的用户和角色在页面上都有样式
  现在我们按照该方法点击保存按钮 会访问 http://127.0.0.1:8000/rbac/distribute/list/?type=x1 页面上的选中效果消失了!!
  所以,该方法不适合该场景
- 正解: 使用隐藏的input表单来实现!!
  ★ <input type="hidden" name="type" value="role">
    <input type="hidden" name="type" value="permission">
  后端
    if request.method == "POST" and request.POST.get("type") == "role":
       pass  # 点击的是角色面板的保存
    if request.method == "POST" and request.POST.get("type") == "permission":
       pass  # 点击的是权限面板的保存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

关键代码如下:

image-20240314221756989

一点小细节

{% block js %}
    <script>
        window.onload = function () {
            // 用于保存成功后,告知用户!!
            let value = "{{ msg }}";
            if (value) {
                layer.msg(value);
            }
        };
        $(function () {
            // ■ 首先要明白一点,右键检查html代码,在页面上给复选框打勾后,对应的checkbox的input元素看起来是没有添加checked的!!
            // 但是你获取该勾选的多选框,该元素.prop("checked") 值为True
            // ■ 再记录下使用layui的checkbox的input 选择框踩的坑.
            // - 你右键检查,在html代码中选中input元素,页面上不会对应高亮的.
            //   而检查页面上对应的选择框,html代码中高亮的是input的相邻的下一个元素
            //   So.点击事件应作用于该元素!!
            $('.dc-check-all .layui-unselect').on('click', function () {
                var obj = $(this).prev("input")
                $(this).parents('.layui-colla-title').next().find(':checkbox').prop('checked', obj.prop('checked'));
                if (obj.prop('checked')) {
                    $(this).parents('.layui-colla-title').next().find('.layui-unselect').addClass("layui-form-checked")
                } else {
                    $(this).parents('.layui-colla-title').next().find('.layui-unselect').removeClass("layui-form-checked")
                }
            });
        })
    </script>
{% endblock %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# RBAC组件应用及完善

在前面的篇幅中, 我们已经开发完成了 RBAC组件 的功能!! 接下来, 需要对其进行应用!!

# 准备工作

我们重新开发一个主机管理程序 来逐步应用 现目前的RBAC组件!!

新建一个python项目host_manage + 利用pycharm构建虚拟环境
pip install Django==3.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
django-admin startproject host_manage .
python manage.py startapp app01
  - 项目根目录下创建apps文件,将app01放到里面
  - 记得将 apps/app01/apps.py 里的 name = 'app01' 改为 name = 'apps.app01'
  - 注册app 'apps.app01.apps.App01Config',
将我们现目前写好的RBAC组件也放到apps目录下,并注册app!!
  - ★ 记得将RBAC组件下的 迁移文件 删除!!
进行Django项目快速启动的配置
1
2
3
4
5
6
7
8
9
10

接下来, 开始 主机管理程序的业务开发. 首当其冲的是, 给主机管理程序进行数据库表的设计!!

# 用户表方案

思考: 业务里的用户表需与rbac组件里的用户表创建关系, 如何创建?
共提供了两个方案, 各有利弊, 最终, 我们采用方案二!!

# 方案一

业务的用户表里 使用 O2O 一对一的外键!!

user = models.OneToOneField(verbose_name="用户", to=RbacUserInfo, on_delete=models.CASCADE) !!

image-20240315142038887

优缺点:

■ 缺点
  用户信息散落在两处,在app01和rbac里都有一部分用户信息/各自存了几列用户数据.
  用户管理功能肯定得将这两处整合到一起进行管理.
  就目前现状而言,经过O2O的设计后:
    rbac里原来的用户管理代码肯定满足不了(eg:字段相较以前,变多了,增加了几个..)
    So,需要在app01里重新写一个! 比如,业务的用户表对象取名字 obj.user.name
■ 优点
  在app01里重新写的代码逻辑,很多都可以借鉴rbac里原来用户管理里的代码,都倒差不差!!
1
2
3
4
5
6
7
8
# 方案二(推荐)

不要分散在两处, 就都放到 业务的用户表中!!

★ 使用继承! + abstract=True

image-20240315145911149

优缺点:

■ 优点
  将用户的所有信息都放到了一张表中(业务的用户表中),对用户信息的维护会更加便捷!!
■ 缺点
  在rbac中所有关于用户的操作,都不能使用啦!!
  rbac中有两处用了rbac的用户表:
    - 用户管理里的CURD+密码重置 => 在rbac中将相关的路由配置注释点
    - 权限分配的第一个面板中会展示所有用户信息,当时读取的就是rbac里的用户表 => 做调整,让它去读区app01业务里的用户表
    

因为使用了abstract=True,所以在rbac组件里admin.py里对rbac的用户表的admin注册将会报错,将其注释掉!!
1
2
3
4
5
6
7
8
9
10
# 开始修改

我们已经确定了使用方案二 - 继承! + abstract=True

我们需要对现已有rbac组件代码进行以下修改:

1. 在rbac组件中有关rbac用户表的CURD+密码重置的相关路由配置进行注释.
   ▲ 意味着用户管理需要在 业务的用户表里 进行操作!!
2. rbac组件的权限分配也用到了rbac的用户表! 权限分配应该用业务中的用户表!
   So,在权限分配之时,读取用户表变成通过配置文件来进行指定并导入.
1
2
3
4

image-20240315173157417

# 业务逻辑开发

开始进行自己的业务开发

注: 在进行业务开发时, 先注释掉母板里的 动态菜单和面包屑导航!! (因为业务开发的模版会继承rbac里的母板

- 部门表 单表的CURD
- 用户表的CURD+重置密码
  - 其实大体上跟原来rbac里用户管理的代码差不多,相比下就是多了些字段 {{ row.get_level_display }} {{ row.depart.title }}..
  - 考虑到有很多用户的话,需要使用分页,分页需要携带原搜索条件,所以会使用 memory_url、memory_reverse 望周知!!
- 主机表的CURD

具体的代码就不做过多阐述啦!!都是学过用过的,经常用的.(¯﹃¯)  我咔咔咔一通cv大法!!
1
2
3
4
5
6
7

就这一通简单的开发下来, 很烦躁, 很多代码都是相似的, 所以 后面我们会开发stark组件来解决这个问题!!

# 注销和首页

添加了 注销和首页的路由!!

Q: 着重思考一个问题: 对于首页、登陆、注销的路由是否需要分配权限呢?
A: 登陆在白名单里,直接就可访问 ; 注销和首页是登陆后才能访问的路由,但无需经过权限验证!!
这导致了, 在中间件里 会分为三种情况: 白名单、登陆但无需权限检验、登陆且需权限校验!! ★

因为我倾向于把登陆功能放到了rbac组件里, 所以 登陆逻辑里使用的 用户表 也要通过 配置文件来进行指定并导入!!

image-20240315213216876

# 应用rbac

业务开发完了, rbac组件也完善的差不多了.
现在开始使用rbac组件来实现对当前开发的主机管理系统的 权限验证、权限批量添加、权限分配等!!

进行下述操作.

当前是注释掉母板里的 动态菜单和面包屑导航 以及 中间件配置 的代码的. 依次进行下面的配置:
- http://127.0.0.1:8000/rbac/menu/list/              在该页面添加1级菜单,  用户管理、权限管理、主机管理
- http://127.0.0.1:8000/rbac/menu/mutil/permissions/ 在该页面批量添加权限,并批量更新它们的所属关系!!
  提醒一点,给权限添加了所属的一级菜单后,该权限就默认变成了可做二级菜单的权限啦!!
- http://127.0.0.1:8000/web/user/list/               添加一个用户"武沛齐"
- http://127.0.0.1:8000/rbac/role/list/              添加一个角色"root"
- http://127.0.0.1:8000/rbac/distribute/list/        在该页面分配权限,给一个用户分配root角色,root角色分配所有权限
■ 至此,你就拥有了一个超级用户"武沛齐"
                                            
- 将layui.html中 动态菜单和面包屑导航的代码应用上
- 中间件注册上 'apps.rbac.utils.verify.RbacMiddleware',
- 白名单的处理 VALID_URL_LIST
- 需要登陆但无需权限校验的路由 NO_PERMISSION_LIST
- 权限的初始化 PERMISSION_SESSION_KEY、MENU_SESSION_KEY
- 批量操作权限时,自动化发现路由中URL时,排除的URL AUTO_DISCOVER_EXCLUDE

做完上述操作,rbac成功配置完毕!! 撒花Bingo~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# RBAC组件使用文档

来总结下, 一个新项目如何快速的应用上 rbac组件!!

Step1: 将rbac组件拷贝项目, 并进行app注册 (使用多app的配置, 放到项目根目录的apps文件夹下!!

Step2: 将rbac组件中 的数据库迁移记录 全部删除.

Step3: 进行业务系统中用户表结构的设计. 遵循: 业务表结构中的用户表需要和rbac中的用户有继承关系

# -- rbac组件的用户表
class UserInfo(models.Model):
    """用户表"""
    name = models.CharField(verbose_name='用户名', max_length=32)
    password = models.CharField(verbose_name='密码', max_length=64)
    email = models.CharField(verbose_name='邮箱', max_length=32)
    roles = models.ManyToManyField(verbose_name='拥有的所有角色', to=Role, blank=True)

    class Meta:
        abstract = True
        
   
# -- 业务系统中的用户表
from apps.rbac.models import UserInfo as RbacUserInfo        
class UserInfo(RbacUserInfo):
    """用户表"""
    phone = models.CharField(verbose_name='联系方式', max_length=32)
    level_choices = (
        (1, 'T1'),
        (2, 'T2'),
        (3, 'T3'),
    )
    level = models.IntegerField(verbose_name='级别', choices=level_choices)
    depart = models.ForeignKey(verbose_name='部门', to='Department', on_delete=models.CASCADE)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

同时, 将业务系统中的用户表的路径写到配置文件!! 用于在rbac分配权限时, 读取业务表中的用户信息!!

# -- settings.py
RBAC_USER_MODLE_CLASS = "apps.app01.models.UserInfo"  # 业务系统中的用户表
1
2

Step4: 开始业务逻辑的开发!! 注意几点.
1> 你可以使用 rabc里的 layout.html 模版! 但切记, 开发业务系统时需将 layout.html 里的 动态菜单和面包屑 的代码注释掉!!
2> 业务系统开发的所有路由, 都必须设置name!! 因为需要用它反向生成url + 自动发现路由 + 按钮级别粒度的控制.

# -- apps/rbac/templates/rbac/layout.html
"""
    <div class="layui-side layui-bg-black sidebar dc_sidebar" id="dc_sidebar">
        <!-- 侧边栏区域 动态菜单-自动生成 ■“业务系统开发过程中注释掉” -->
        {% multi_menu request %} 
    </div>

    <div class="content dc_content" id="dc_content">
        <!-- 内容主体区域 -->
        <div style="padding: 35px; position: relative;">
            <div style="position: absolute;left: 3px;top:3px" onclick="toggleSidebar()">
                <i class="layui-icon layui-icon-release" style="font-size: 20px; color: slategray;"></i>
            </div>
            <div style="margin-bottom: 25px">
                <!-- 面包屑导航 自动生成 ■“业务系统开发过程中注释掉”-->
                {% url_record request %}
            </div>
            {% block content %} {% endblock %}
        </div>
    </div>
"""

# -- 业务系统的路由
url(r'^host/list/$', host.host_list, name='host_list'),
url(r'^host/add/$', host.host_add, name='host_add'),
url(r'^host/edit/(?P<pk>\d+)/$', host.host_edit, name='host_edit'),
url(r'^host/del/(?P<pk>\d+)/$', host.host_del, name='host_del'),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Step5: 进行权限信息的录入

首先, 你需要在根路由中 添加 rbac组件的路由分发, 注意哦, 必须设置其namespace为"rbac"

path('rbac/', include('apps.rbac.urls', namespace="rbac")),  # rbac组件
path('web/', include('apps.app01.urls')),  # 业务系统
1
2

接着, 你要知道在批量添加页面是会自动发现项目中的路由的, 有些路由是无需自动发现的!!

# -- settings.py
# 批量操作权限时,自动化发现路由中URL时,排除的URL
AUTO_DISCOVER_EXCLUDE = [
    '/admin/.*',
    '/rbac/login/',
    '/rbac/logout/',
    '/rbac/index/',
]

# -- 上面登陆、登出、首页使用的是rbac组件内部的,但大多数时候我们会在业务app里自己写并且将其路由配置到根路由里
#    所以,该场景下,排除的URL配置,应该像下面这样写  (- 将rbac里登陆、登出、首页的路由配置注释掉就行!!)
AUTO_DISCOVER_EXCLUDE = [
    '/admin/.*',
    '/login/',
    '/logout/',
    '/index/',
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

接着, 依次在下面地址中进行操作

- http://127.0.0.1:8000/rbac/menu/list/              在该页面添加一级菜单,  eg: 用户管理、权限管理、主机管理
- http://127.0.0.1:8000/rbac/menu/mutil/permissions/ 在该页面批量添加权限,并批量更新它们的所属关系!!
  提醒一点,给权限添加了所属的一级菜单后,该权限就默认变成了可做二级菜单的权限啦!!
- http://127.0.0.1:8000/web/user/list/               eg: 添加一个用户"武沛齐"
- http://127.0.0.1:8000/rbac/role/list/              eg: 添加一个角色"root"
- http://127.0.0.1:8000/rbac/distribute/list/        在该页面分配权限,给"武沛齐"用户分配root角色,root角色分配所有权限
■ 至此,你就拥有了一个超级用户"武沛齐"
1
2
3
4
5
6
7

Step6: 编写用户的登录逻辑

你可以使用rbac自带的登录、注销、首页 的逻辑!! 当然, 你偏要自己写的话, 有一点你必须注意:

# -- must do it (one): 在用户登录成功后,执行该语句!!
from apps.rbac.utils.initialize import init_permission
init_permission(current_user, request)  # 用户权限信息的初始化

# -- must do it (two): settings需进行相关配置
# 权限在Session中存储的key
PERMISSION_SESSION_KEY = "permission_url_list_key"
# 菜单在Session中存储的key
MENU_SESSION_KEY = "menu_list_key"
1
2
3
4
5
6
7
8
9

Step7: 在setting中注册rbac中用于权限校验的中间件!! 以及相关的配置.

MIDDLEWARE = [
    # ... ... ...
    'apps.rbac.utils.verify.RbacMiddleware',
]

# 白名单,无需登陆即可访问
VALID_URL_LIST = [
    '/rbac/login/',
    '/admin/.*',
    '/favicon.ico',
]

# 需要登录但无需权限的URL / 登陆后的每个人都默认拥有的权限 / 登陆后不用做权限校验的路由
NO_PERMISSION_LIST = [
    '/rbac/index/',
    '/rbac/logout/',
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Ok, 到这一步, 你就可以 将layout.html 里 动态菜单和面包屑 的相关代码 的注释取消掉/应用上啦!!

Step8: 在业务系统的前端模版中, 进行粒度到按钮级别的控制

{% load button_permission %}

{% if request|has_permission:'host_edit' %}
<a href="{% memory_url request 'host_edit' row.pk %}">
    <button type="button" class="layui-btn layui-btn-sm layui-btn-primary">
        <i class="layui-icon layui-icon-edit"></i>
    </button>
</a>
{% endif %}
1
2
3
4
5
6
7
8
9

说在后面, 简略版:

总结,目的是希望在任意系统中应用权限系统。
- 用户登录 + 用户首页 + 用户注销 业务逻辑
- 项目业务逻辑开发
  注意: 开发时候灵活的去设置layout.html中的两个inclusion_tag "开发时,去掉;上下线运行时,取回"
- 权限信息的录入
- 配置文件
# 注册APP
INSTALLED_APPS = [
    # ... ... ...
    'apps.rbac.apps.RbacConfig',
]
# 应用中间件
MIDDLEWARE = [
    # ... ... ...
    'apps.rbac.utils.verify.RbacMiddleware',
]

# #################### 权限相关配置 #######################
# 业务中的用户表
RBAC_USER_MODLE_CLASS = "apps.app01.models.UserInfo"
# 权限在Session中存储的key
PERMISSION_SESSION_KEY = "permission_url_list_key"
# 菜单在Session中存储的key
MENU_SESSION_KEY = "menu_list_key"

# 白名单,无需登陆即可访问
VALID_URL_LIST = [
    '/rbac/login/',
    '/admin/.*',
    '/favicon.ico',
]

# 需要登录但无需权限的URL / 登陆后的每个人都默认拥有的权限 / 登陆后不用做权限校验的路由
NO_PERMISSION_LIST = [
    '/rbac/index/',
    '/rbac/logout/',
]

# 批量操作权限时,自动化发现路由中URL时,排除的URL
AUTO_DISCOVER_EXCLUDE = [
    '/admin/.*',
    '/rbac/login/',
    '/rbac/logout/',
    '/rbac/index/',
]
- 粒度到按钮级别的控制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

大工告成!!

菜单和权限管理
自动生成

← 菜单和权限管理 自动生成→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式