设计表结构
models中创建类:五个类,七张表
角色表: 用户表: 权限表:权限组表:
菜单表:
角色表和权限表是多对多的关系(一个角色可以有多个权限,一个权限可以对应多个角色)
用户表和角色表是多对多的关系(一个用户可以有多个角色,一个角色有多个用户)所以有会多生成两张关系表
一个菜单下面有多个组
一个组下面有多个菜单
一个菜单下面有多个权限
对于菜单的展示要求: 用户访问的url:/users/ 1 /users/所在的菜单展开,其它菜单收起来 2 /users/权限对应的a标签加active样式
想要的数据格式样式 menu_dict={ 1:{ "title":"菜单一", "active":True, "children":[ {"title":"添加用户","url":"xxxxxxxxxxx","active":False}, {"title":"查看用户","url":"xxxxxxxxxxx","active":True}, ]}, 2:{ "title":"菜单二", "active":False, "children":[ {"title":"添加用户","url":"xxxxxxxxxxx","active":False}, {"title":"查看用户","url":"xxxxxxxxxxx","active":False}, ] }
# 修改表结构问题一:
需求:每一个组代表一张表,以permissionGruop为一级菜单,会导致一级菜单过多,展示效果不理想
每个一级菜单最多只有2个二级菜单(对应的权限太少) 解决: 给permissionGroup组再分组menu class Menu(一级菜单) id caption 1 用户角色管理 将角色组和用户组融合在一起
显示的样式
为什么菜单栏不显示删除及编辑用户(含有正则)?
在页面无法给(\d+)传数据
需求2: 注意:含正则表达式的权限不能放在菜单栏 解决办法: 在同一组中,将不会放入菜单栏中的权限归属到放到菜单栏中的权限 is_menu parent 1 查看用户列表 /users/ 用户组 list True null 2 添加用户 /users/add/ 用户组 add False 1 3 删除用户 /users/delete/(\d+) 用户组 delete False 1 4 编辑用户 /users/edit/(\d+) 用户组 edit False 1 5 查看订单列表 /orders/ 订单组 list True null 6 添加订单 /orders/add/ 订单组 add False 5 7 删除订单权限 /orders/delete/(\d+) 订单组 delete False 5 8 编辑订单 /orders/edit/(\d+) 订单组 edit False 5 对于权限表的某一个组中,对于加入菜单栏中的权限记录,让字段parent为null,如果不的话,parent归属到该组中加入菜单栏的权限中 所以在permission加一个自关联字段 # 关于字段parent 1的意思:归属到自关联字段users,菜单栏没有我,但要有我的归属 # 权限显示,但要只知道哪一个权限要标红 例如:
# [{'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1}, # {'id': 2, 'url': '/users/add/', 'title': '添加用户', 'pid': 1, 'menu_name': '用户角色管理', 'menu_id': 1}, # {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}]关于pid的作用但为none就要显示在菜单栏中
关于设计菜单管理-----问题: 1、如何生成菜单2、怎么让这些菜单分级显示并且如果当前访问的url权限默认展开如果是组内菜单就加粗或者变红3、非菜单url,默认选中原菜单。(如果你是点击用户列表进来的,那么你看到页面了,如果你点击添加的时候,你的那个用户列看不见了,这就不好了。 所以要设计当你点击添加按钮的时候,那个用户列表被默认选中)菜单管理 菜单一 用户管理 权限管理 菜单二 订单管理 角色管理分级做了菜单。这些菜单该显示什么菜单?是当前用户登录之后从数据库拿到这个用户拥有的权限,然后把权限搞成菜单在表里面设计了一个组内菜单(自关联 ),当pid为NULL就代表可以作为菜单
用户访问的路径有2种情况: 1:不含有正则的url----> 要展示在菜单栏(通过pid是否为None来判断) 2:含有正则的url----> 不在菜单栏里显示(但要找到它的归属,将展开并高亮)
怎样获得菜单栏的数据结构及处理
# 在initial中间件完成 # 用户的权限信息 permission_info = user.roles.all().values("permissions__id", "permissions__url", "permissions__title", "permissions__permission_group_id", # 权限的组 "permissions__code", # 权限的编号 "permissions__parent_id", # 权限的一级菜单 "permissions__permission_group__menu__caption", # 分组的组的名字 "permissions__permission_group__menu_id", ).distinct() # print('permission_info',permission_info) # permission_info < QuerySet[{'permissions__id': 5, # 'permissions__url': '/orders/', # 'permissions__title': '查看订单列表', # 'permissions__permission_group_id': 3, # 'permissions__code': 'list', # 'permissions__parent_id': None, # 'permissions__permission_group__menu__caption': '订单管理', # 'permissions__permission_group__menu_id': 2}] > # 8个键值对太多了,名字太长,下面是用来简化数据 # 创建生成菜单的数据 ---> 简化上面的数据 permission_list=[] for permission_item in permission_info: temp={ "id":permission_item["permissions__id"], "url":permission_item["permissions__url"], "title":permission_item["permissions__title"], "pid":permission_item["permissions__parent_id"], "menu_name":permission_item["permissions__permission_group__menu__caption"], "menu_id":permission_item["permissions__permission_group__menu_id"] } permission_list.append(temp) request.session["permission_list"]=permission_list # 有几个权限就有几个字典 # print(permission_list) # [{'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}]
""" 有几个权限就有几个字典 [{'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1}, {'id': 2, 'url': '/users/add/', 'title': '添加用户', 'pid': 1, 'menu_name': '用户角色管理', 'menu_id': 1}, {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}] """ # 当pid为none就要显示在菜单栏中,过滤掉pid有值的 # temp_dict 过滤掉的数据,只放pid为none------> 存储所有放到菜单栏中的权限 ---> 调整active # 显示在菜单栏的数据 temp_dict = {} for item in permission_list: pid = item["pid"] if not pid: item["active"] = False # 添加标志状态 temp_dict[item["id"]] = item # 可变数据类型 # print(temp_dict) # {1: {'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1, 'active': False}, # 5: {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2, 'active': False}}# 当不是在菜单栏处理 # 取到用户输入的url,path_info是request提供的方法 current_path = request.path_info import re for item in permission_list: pid = item["pid"] url = "^%s$" % item["url"] if re.match(url, current_path): if pid: # 有值,设置他的归属(高亮) temp_dict["pid"]["active"] = True else: # 没有,设置自己 item["active"] = True# 此时的item是可能含有带有正则的url,通过pid找到它的归属菜单栏,修改其active的状态# 当访问的url是要在菜单栏显示的:直接修改自己的active的状态,将其变红#问题1: 为什么循环的是permission_list而不是temp_dict?temp_dict里面的数据是要显示在菜单栏里的,其url是不包含正则而permission_list里面是用户所有权限的url,当访问的url含有正则,且是用户的权限,虽然不显示在菜单栏,但也要修改其归属菜单的active的状态# 问题2: 上面的代码在处理active的状态,但最终要处理数据是temp_dict,而不是permission_list? 因为它们两个都是引用同一个数据类型(permission_list),上面本质也不是改permission_list里面的active而是改temp_dict,它们两个是关联的想要构成的数据格式 """ menu_dict = { 1: { "title": "用户角色管理", "active": True, "children": [ {"title": "添加用户", "url": "xxxxxxxxxxx", "active": False}, {"title": "查看用户", "url": "xxxxxxxxxxx", "active": True}, ]}, 2: { "title": "订单管理", "active": False, "children": [ {"title": "添加用户", "url": "xxxxxxxxxxx", "active": False}, {"title": "查看用户", "url": "xxxxxxxxxxx", "active": False}, ] }} """ # 将temp_dict转换为最终想要的格式 menu_dict = {} for item in temp_dict.values(): if item["menu_id"] in menu_dict: # 有就添加,没有就创建 temp = { "title": item["title"], "url": item["url"], "active": item["active"]}, menu_dict[item["menu_id"]]["children"].append(temp) if item["active"]: # 用户的active为True,则将父亲的active改为True menu_dict[item["menu_id"]]["active"] = True else: menu_dict[item["menu_id"]] = { "title": item["menu_name"], "active": item["active"], "children": [ { "title": item["title"], "url": item["url"], "active": item["active"]} ] } print(menu_dict){ 2: { 'title': '订单管理', 'active': True, 'children': [{ 'title': '查看订单列表', 'url': '/orders/', 'active': True}]}}
关于自定义标签1、先创建templatetags文件夹 在里面创建一个模板文件my_tags.py2、导入模块(register的名字是固定的,不可改变) from django import template register=template.Library() @register.simple_tag def mul(x,y): return x*y 3、在需要使用的页面导入模板(使用模板) {% load my_tags %} 4:、在调用模板函数 {% mul 2 4 %}
关于权限利用到的自定义标签
1、先创建templatetags文件夹 在里面创建一个模板文件my_tags.py
2、导入模块(register的名字是固定的,不可改变) from django import template register=template.Library() @register.inclusion_tag("menu.html") def get_menu(request): ... return { "menu_dict":menu_dict} # 将数据传到menu.html 3: 创建一个独立显示菜单的页面menu.html 4: 在base页面调用模板的函数 {% get_menu request %}
@register.inclusion_tag("menu.html")def get_menu(request): # 从session中取出数据 permission_list = request.session["permission_list"] """ 有几个权限就有几个字典 [{'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1}, {'id': 2, 'url': '/users/add/', 'title': '添加用户', 'pid': 1, 'menu_name': '用户角色管理', 'menu_id': 1}, {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2}] """ # 当pid为none就要显示在菜单栏中,过滤掉pid有值的 # temp_dict 过滤掉的数据,只放pid为none------> 存储所有放到菜单栏中的权限 ---> 调整active temp_dict = {} for item in permission_list: pid = item["pid"] if not pid: item["active"] = False # 添加标志状态 temp_dict[item["id"]] = item # 可变数据类型 # print(temp_dict) # {1: {'id': 1, 'url': '/users/', 'title': '查看用户列表', 'pid': None, 'menu_name': '用户角色管理', 'menu_id': 1, 'active': False}, # 5: {'id': 5, 'url': '/orders/', 'title': '查看订单列表', 'pid': None, 'menu_name': '订单管理', 'menu_id': 2, 'active': False}} # 取到用户输入的url,path_info是request提供的方法 current_path = request.path_info import re for item in permission_list: pid = item["pid"] url = "^%s$" % item["url"] if re.match(url, current_path): if pid: # 有值,设置他的归属(高亮) temp_dict["pid"]["active"] = True else: # 没有,设置自己 item["active"] = True # 将temp_dict转换为最终想要的格式 menu_dict = {} for item in temp_dict.values(): if item["menu_id"] in menu_dict: # 有就添加,没有就创建 temp = { "title": item["title"], "url": item["url"], "active": item["active"]}, menu_dict[item["menu_id"]]["children"].append(temp) if item["active"]: # 用户的active为True,则将父亲的active改为True menu_dict[item["menu_id"]]["active"] = True else: menu_dict[item["menu_id"]] = { "title": item["menu_name"], "active": item["active"], "children": [ { "title": item["title"], "url": item["url"], "active": item["active"]} ] } print(menu_dict) return { "menu_dict":menu_dict}
{ # 封装,在哪里调用都可以使用到左侧菜单内容 #}{ #这只是样式,布局可能有了#}