组建策划之可插拔权限组件(下):RBAC

rbac组件全面优化及知识点详解

Posted by QQL on January 15, 2019

技术点一:批量操作权限(添加/修改/删除)实现思路

1. 获取项目中所有权限 set1
2. 去数据库中获取已经录入的所有权限 set2

情况一: 自动发现 > 数据库 —-> 实现批量添加 ps:通过name进行对比
 set1 - set2 —–> 添加
 场景:第一次进入系统,自动发现一堆路由,都没有录入到数据库中,需要批量的增加路由到数据库中

情况二:数据库 > 自动发现 —->实现批量删除
 set2 - set1 —–> 删除
 场景:已经开发了的路由,项目突然不需要某些已有的路由,在后端路由注释掉,导致自动发现不了,但数据库中已经存在项目路由,则需要批量删除不需要的路由

情况三:自动发现 = 数据库已有的 —–>实现批量更新
 set3 = set1&set2 —–>更新  场景:需要修改已有路由的url路径/name/名称等信息

技术点二:数据构造

在需要多层嵌套数据时,例如三级菜单,多级权限等场景。我们就需要构造特殊的数据格式,满足前端样式的层级渲染。
通常我们在最外层格式使用字典:

{
    1:{'id': 1, 'title': '菜单1'},
    2:{'id': 2, 'title': '菜单2'},
    3:{'id': 3, 'title': '菜单3'},
}

字典的key必须为唯一的数据,例如数据库中id主键,或其他一些Unique的字段。有了字典就可以使用
if xxx in dict:pass 来快速判断字典里是否有xxx数据。因为字典的数据结构是hash。
在字典数据的内层,使用字段:[{},{},....]来实现多层结构,例如:

    [
        {id:1,title:x1, menu_id:1,children:[{id:11,title:x2,pid:1},{},....] },   
        {id:2,title:x1, menu_id:1,children:[] },
        {id:3,title:x1, menu_id:2,children:[] },
        {id:4,title:x1, menu_id:3,children:[] },
        {id:5,title:x1, menu_id:2,children:[] },
    ]

值得注意的是,这些数据格式往往在web开发中有对应的格式,例如:

models.xxx.objects.values('id','title',.....) --->拿到[{},{},...]的格式
models.xxx.objects.value_list('id','title',.....) --->拿到[(),()...]的格式

容易遗漏的情况

列表和字典都是可变类型

menu_list = [
    {'id': 1, 'title': '菜单1'},
    {'id': 2, 'title': '菜单2'},
    {'id': 3, 'title': '菜单3'},
]

menu_dict = {}
"""
{
    1:{'id': 1, 'title': '菜单1'},
    2:{'id': 2, 'title': '菜单2'},
    3:{'id': 3, 'title': '菜单3'},
}
"""
for item in menu_list:
    menu_dict[item['id']] = item

# menu_dict[2]['title'] = '666'

menu_dict[2]['children'] = [11,22]  # 修改了同一个可变类型dict

print(menu_list)
"""
print打印出
[
    {'id': 1, 'title': '菜单1'}, 
    {'id': 2, 'title': '菜单2', 'children': [11, 22]}, 
    {'id': 3, 'title': '菜单3'}
]
"""

python为了节约空间,给变量赋一个可变类型(list/dict),并没有给变量创建了新的list/dict,而是指向了原本同一个list/dict,我们可以利用这点,为这个变量进行值的修改,则相当于同步修改了原数据list/dict。
如果想要达到变量互不相关的效果,则需要深copy一份可变类型给变量