rbac组件之动态二级菜单之路径导航

在之前的版本中,左上角路径导航在html页面写死了,如:

rbac组件之动态二级菜单之路径导航

 

 

 那么我们需要做一个根据用户的不同操作从而实现路径导航的自动变化,如:

rbac组件之动态二级菜单之路径导航

 

 

 第一步:在权限初始化的时候,对ORM取出的数据以及权限数据信息进行更改

from django.conf import settings


def init_permission(current_user, request):
    permission_queryset = current_user.roles.filter(
        permissions__isnull=False,
    ).values(
        "permissions__id",  # 二级菜单id
        "permissions__url",  # 二级菜单url
        "permissions__title",  # 二级菜单名称
        "permissions__menu__id",  # 一级菜单ID
        "permissions__menu__title",  # 一级菜单名称
        "permissions__menu__icon",  # 一级菜单图标
        "permissions__pid_id",  # 非菜单url的自关联pid值,如果是二级菜单那么该字段值为空
        "permissions__pid__title",  # 路径导航
        "permissions__pid__url",  # 路径导航
    ).distinct()
    permission_list = []  # 存放用户的权限数据信息
    menu_dict = {}  # 存放菜单信息
    for item in permission_queryset:
        # 权限信息数据结构变为列表套字典
        permission_list.append(
            {
                "id": item["permissions__id"],  # 如果是二级菜单,那么需要用到此字段与菜单信息进行比较
                "url": item["permissions__url"],
                "title": item["permissions__title"],  # 路径导航
                "pid": item["permissions__pid_id"],  # 如果此字段为空,那么说明该url是二级菜单;如果不为空,那么需要用此字段与菜单信息进行比较
                "p_title": item["permissions__pid__title"],  # 路径导航
                "p_url": item["permissions__pid__url"],  # 路径导航
            }
        )
        menu_id = item["permissions__menu__id"]  # 取到二级菜单所对应的一级菜单的id,如果不能做二级菜单的,那么这个字段值是null
        if not menu_id:
            continue
        node = {
            "id": item["permissions__id"],
            "title": item["permissions__title"],
            "url": item["permissions__url"],
        }  # 二级菜单数据信息,方便后续添加
        if menu_id in menu_dict:
            menu_dict[menu_id]["children"].append(node)  # 如果一级菜单已经存在,那么直接添加二级菜单数据信息即可
        else:
            # 如果一级菜单不存在,那么还需要添加一级菜单的数据信息和二级菜单的数据信息
            menu_dict[menu_id] = {
                "title": item["permissions__menu__title"],
                "icon": item["permissions__menu__icon"],
                "children": [node, ],
            }
    print(permission_list)
    request.session[settings.PERMISSION_SESSION_KEY] = permission_list
    request.session[settings.MENU_SESSION_KEY] = menu_dict


"""
权限信息
permission_list = [
                    {'id': 1, 'url': '/customer/list/', 'title': '客户列表', 'pid': None, 'p_title': None, 'p_url': None},
                    {'id': 2, 'url': '/customer/add/', 'title': '添加客户', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 3, 'url': '/customer/list/(?P<cid>\\d+)/', 'title': '删除客户', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 4, 'url': '/customer/edit/(?P<cid>\\d+)/', 'title': '修改客户', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 5, 'url': '/customer/import/', 'title': '批量导入', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 6, 'url': '/customer/tpl/', 'title': '下载模板', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 7, 'url': '/payment/list/', 'title': '账单列表', 'pid': None, 'p_title': None, 'p_url': None},
                    {'id': 8, 'url': '/payment/add/', 'title': '添加账单', 'pid': 7, 'p_title': '账单列表', 'p_url': '/payment/list/'},
                    {'id': 9, 'url': '/payment/del/(?P<pid>\\d+)/', 'title': '删除账单', 'pid': 7, 'p_title': '账单列表', 'p_url': '/payment/list/'},
                    {'id': 10, 'url': '/payment/edit/(?P<pid>\\d+)/', 'title': '修改账单', 'pid': 7, 'p_title': '账单列表', 'p_url': '/payment/list/'}
                    ]
菜单信息
menu_dict = {'1': {
                    'title': '信息管理', 
                    'icon': 'fa-camera-retro',
                    'children': [{'id': 1, 'title': '客户列表', 'url': '/customer/list/'}]},
            '2': {
                    'title': '用户管理', 
                    'icon': 'fa-fire',
                    'children': [{'id': 7, 'title': '账单列表', 'url': '/payment/list/'}]}}
"""

第二步:在中间件新建一个默认列表,列表第一个数据为{"title": "首页", "url": "#"},然后基于此列表再添加路径,对权限信息中的pid进行判断,如果为空,则加一个,如果不为空,则加两个(一个是二级菜单,一个是当前操作的url对应的title)

from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
import re
from django.shortcuts import HttpResponse


class RbacMiddleware(MiddlewareMixin):
    def process_request(self, request):
        current_url = request.path_info
        for url in settings.VALID_URL_LIST:
            if re.match(url, current_url):
                return None
        permission_list = request.session.get(settings.PERMISSION_SESSION_KEY)
        if not permission_list:
            return HttpResponse("未获取到用户权限信息,请重新登录...")
        flag = False
        url_record = [
            {"title": "首页", "url": "#"},
        ]  # 路径导航列表
        for url in permission_list:
            reg = "^%s$" % url["url"]
            if re.match(reg, current_url):
                flag = True
                request.current_selected_permission = url["pid"] or url["id"]  # pid不为空,那么值为pid;pid为空,那么值为id
                # 路径导航
                if not url["pid"]:
                    url_record.extend(
                        [{"title": url["title"], "url": url["url"], "class": "active"}]
                    )
                else:
                    url_record.extend(
                        [
                            {"title": url["p_title"], "url": url["p_url"]},
                            {"title": url["title"], "url": url["url"], "class": "active"},
                        ]
                    )
                request.url_record = url_record  # 路径导航
                break
        if not flag:
            return HttpResponse("你无权访问,请速速撤离...")


"""
permission_list = [
                    {'id': 1, 'url': '/customer/list/', 'title': '客户列表', 'pid': None, 'p_title': None, 'p_url': None},
                    {'id': 2, 'url': '/customer/add/', 'title': '添加客户', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 3, 'url': '/customer/list/(?P<cid>\\d+)/', 'title': '删除客户', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 4, 'url': '/customer/edit/(?P<cid>\\d+)/', 'title': '修改客户', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 5, 'url': '/customer/import/', 'title': '批量导入', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 6, 'url': '/customer/tpl/', 'title': '下载模板', 'pid': 1, 'p_title': '客户列表', 'p_url': '/customer/list/'},
                    {'id': 7, 'url': '/payment/list/', 'title': '账单列表', 'pid': None, 'p_title': None, 'p_url': None},
                    {'id': 8, 'url': '/payment/add/', 'title': '添加账单', 'pid': 7, 'p_title': '账单列表', 'p_url': '/payment/list/'},
                    {'id': 9, 'url': '/payment/del/(?P<pid>\\d+)/', 'title': '删除账单', 'pid': 7, 'p_title': '账单列表', 'p_url': '/payment/list/'},
                    {'id': 10, 'url': '/payment/edit/(?P<pid>\\d+)/', 'title': '修改账单', 'pid': 7, 'p_title': '账单列表', 'p_url': '/payment/list/'}
                    ]
"""

第三步:写inclusion_tag

from django.template import Library
from django.conf import settings
import re
from collections import OrderedDict


register = Library()


@register.inclusion_tag("rbac/url_record.html")
def url_record(request):
    return {"url_record": request.url_record}

第四步:写inclusion_tag返回的html

<div>
    <ol class="breadcrumb no-radius no-margin" style="border-bottom: 1px solid #ddd;">
        {% for item in url_record %}
            {% if item.class %}
                <li class="{{ item.class }}">{{ item.title }}</li>
                {% else %}
                    <li><a href="{{ item.url }}">{{ item.title }}</a></li>
            {% endif %}
        {% endfor %}
    </ol>
</div>

第五步:前端应用该inclusion_tag

{% load rbac %}

{% url_record request %}

链接:https://pan.baidu.com/s/19DzXcRUPa8ockyqTRE72WA
提取码:abab

上一篇:【网站可用性自动化监测】python+seleium


下一篇:javascript-将可观察的转换为可观察的