• 权限管理-菜单管理 + 递归生成菜单


    from app import models
    import re
    from functools import wraps
    from django.shortcuts import HttpResponse, redirect


    class PermissionHelper(object):

    def __init__(self, request, user):
    self.user = user #userID
    self.request = request #request对象
    self.current_url = request.path_info #获取用户输入的当前路径
    self.permission2role_dict = None #权限显示效果{"/index":"add"}
    self.menu_leaf_list = None #有url的叶子节点
    self.menu_list = None #所有的菜单
    self.session_data() #把所有权限注册到session中

    def session_data(self):
    permission_dict = self.request.session.get("permission_info") #从session中取出数据
    if permission_dict: #如果数据在session中存在把数据取出赋值给对象变量
    self.permission2role_dict = permission_dict["permission2role_dict"]
    self.menu_leaf_list = permission_dict["menu_leaf_list"]
    self.menu_list = permission_dict["menu_list"]
    else:
    #如果session不存在从数据库中取出数据注入到session中
    role_list = models.Role.objects.filter(role2userinfo__user=self.user) #取出当前登录用户的所有角色

    permission2role_list = models.Permission2Action.objects.filter(permission2action2role__role__in=role_list).
    values("p__url", "a__code").distinct() #取出当前登录用户所有角色的url和antion并去重

    permission2role_dict = {}
    #转换数据格式把数据从queryset中取出存在字典中 权限显示效果{"url":"对应的权限操作"}
    for item in permission2role_list:
    item = {
    "url": item["p__url"],
    "code": item["a__code"]
    }
    if item["url"] in permission2role_dict:
    permission2role_dict[item["url"]].append(item["code"])
    else:
    permission2role_dict[item["url"]] = [item["code"], ]
    #取出所有url的叶子节点
    menu_leaf_list = list(models.Permission2Action.objects.filter(permission2action2role__role__in=role_list).
    exclude(p__menu__isnull=True).values("p__id", "p__title", "p__url",
    "p__menu").distinct())
    #取出所有菜单
    menu_list = list(models.Menu.objects.values("id", "title", "parent_id"))
    #把所有权限注入到session中
    self.request.session["permission_info"] = {
    "permission2role_dict": permission2role_dict,
    "menu_leaf_list": menu_leaf_list,
    "menu_list": menu_list
    }
    #第一次登录session中没有数据把数据赋值给对象变量
    self.permission2role_dict = permission2role_dict
    self.menu_leaf_list = menu_leaf_list
    self.menu_list = menu_list

    #生成权限菜单显示效果[{id:1,child:[{id:3,child[{id:5,child:[]}]}]}]
    def menu_data_list(self):
    menu_leaf_dict = {}
    open_menu_leaf_parent_id = None

    for item in self.menu_leaf_list: #取出所有存在URL的叶子节点
    item = {
    "id": item["p__id"],
    "title": item["p__title"],
    "url": item["p__url"],
    "parent_id": item["p__menu"],
    "child": [], #添加挂靠的列表
    "status": True, #添加显示状态
    "open": False, #添加菜单的激活状态
    }
    if re.match(item["url"], self.current_url): #匹配URL是否是当前用户输入的URL
    item["open"] = True #如果匹配成功就激活
    open_menu_leaf_parent_id = item["parent_id"] #保存当前激活状态的URL的parentid用来匹配上级菜单

    if item["parent_id"] in menu_leaf_dict: #更改数据结构结果为{1:["id":...,'child':[]]}
    menu_leaf_dict[item["parent_id"]].append(item)
    else:
    menu_leaf_dict[item["parent_id"]] = [item, ]

    menu_dict = {}

    for item in self.menu_list: #取出所有的菜单并添加child,显示状态和激活状态
    item["child"] = []
    item["status"] = False
    item["open"] = False
    menu_dict[item["id"]] = item #更改数据结构显示为{1:{"id":...},2:{"id":....}}

    while open_menu_leaf_parent_id: #更改父节点的激活状态如果是当前激活的URL就把当前URL父节点的所有激活状态改为True
    menu_dict[open_menu_leaf_parent_id]["open"] = True
    open_menu_leaf_parent_id = menu_dict[open_menu_leaf_parent_id]["parent_id"]

    for k, v in menu_leaf_dict.items(): #把所有叶子节点的信息挂靠到父节点的child中
    menu_dict[k]["child"] = v
    parent_id = k
    while parent_id:
    menu_dict[parent_id]["status"] = True #更改所有存在叶子节点的父节点的显示状态
    parent_id = menu_dict[parent_id]["parent_id"]

    result = []

    for row in menu_dict.values():
    if row["parent_id"]: #遍历菜单把存在parent_id的菜单都挂靠到父节点上
    menu_dict[row["parent_id"]]["child"].append(row)
    else:
    result.append(row)

    return result

    def menu_content(self, content_list): #递归生成所有子菜单
    response = ""
    tpl = """
    <div class="item %s">
    <div class="title">%s</div>
    <div class="content">%s</div>
    </div>
    """
    for row in content_list:
    if not row["status"]:
    continue
    active = ""
    if row["open"]:
    active = "active"
    title = row["title"]
    content = self.menu_content(row["child"])
    if "url" in row:
    response += '<a class="%s" href="%s">%s</a>' % (active, row["url"], row["title"])
    else:
    response += tpl % (active, title, content)
    return response

    def menu_tree(self): #生成所有父菜单
    response = ""
    tpl = """
    <div class="item %s">
    <div class="title">%s</div>
    <div class="content">%s</div>
    </div>
    """
    for row in self.menu_data_list():
    if not row["status"]:
    continue
    active = ""
    if row["open"]:
    active = "active"
    title = row["title"]
    content = self.menu_content(row["child"])
    response += tpl % (active, title, content)
    return response

    def actions(self): #取出当前登录的用户的所有操作权限

    action_list = []

    for key, value in self.permission2role_dict.items():
    if re.match(key, self.current_url):
    action_list.append(value)

    return action_list


    def permission(func): #权限验证装饰器
    @wraps(func)
    def inner(request, *args, **kwargs):
    user_id = request.user.pk
    if not user_id:
    return redirect("/login/")
    permission_obj = PermissionHelper(request, user_id)
    action_list = permission_obj.actions()
    if not action_list:
    return HttpResponse("没有权限访问")
    kwargs["menu_str"] = permission_obj.menu_tree()
    kwargs["action_list"] = action_list
    return func(request, *args, **kwargs)
    return inner

  • 相关阅读:
    爬虫基础
    设计BBS
    中间件和auth模块
    git
    分页器与form表单
    cookie与session
    springboot2.x基础教程:@Enable原理
    springboot2.x基础教程:@Scheduled开启定时任务及源码分析
    springboot2.x基础教程:@Async开启异步任务
    springboot2.x基础教程:JRebel实现SpringBoot热部署
  • 原文地址:https://www.cnblogs.com/louzi/p/9461116.html
Copyright © 2020-2023  润新知