权限组件(4):给动态菜单增加面包屑导航

效果图:

一、在初始化权限的时候增加二级菜单的标题和url

这么做是为了在中间件中把二级菜单和具体权限的标题、url都储存起来
rbac/service/init_permission.py

from permission_learn import settings


def init_permission(current_user, request):
    """
    用户权限的初始化
    :param current_user:  当前登录用户
    :param request:
    :return:
    """

    permission_menu_queryset = current_user.roles.filter(permissions__isnull=False).values(
        'permissions__id',
        'permissions__title',
        'permissions__url',
        'permissions__pid_id',
        'permissions__pid__title',  # +
        'permissions__pid__url',    # + 
        'permissions__menu_id',
        'permissions__menu__title',
        'permissions__menu__icon',
    )

    permission_list = []

    menu_dict = {}

    for item in permission_menu_queryset:
        permission_list.append({
            'id': item['permissions__id'],
            'title': item['permissions__title'],
            'url': item['permissions__url'],
            'pid': item['permissions__pid_id'],  # + 
            'p_title': item['permissions__pid__title'],    # +
            'p_url': item['permissions__pid__url'],
        })

        menu_id = item['permissions__menu_id']

        if not menu_id:
            continue

        second_menu = {'id': item["permissions__id"], 'title': item['permissions__title'],
                       'url': item['permissions__url']}

        if menu_id in menu_dict:
            menu_dict[menu_id]['second_menu'].append(second_menu)
        else:
            menu_dict[menu_id] = {
                'title': item['permissions__menu__title'],
                'icon': item['permissions__menu__icon'],
                'second_menu': [second_menu, ]
            }

    request.session[settings.PERMISSION_SESSION_KEY] = permission_list
    request.session[settings.MENU_SESSION_KEY] = menu_dict

二、中间件处理

rbac/middlewares/rbac.py

import re

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
from permission_learn import settings


class RbacMiddleware(MiddlewareMixin):
    def process_request(self, request):

        white_list = settings.WHITE_LIST

        current_path = request.path

        for valid_url in white_list:
            if re.match(valid_url, current_path):
                return None

        permission_list = request.session.get(settings.PERMISSION_SESSION_KEY)

        if not permission_list:
            return HttpResponse('请先登录 ')

        has_permission = False

        url_record = [
            {'title': '首页', 'url': '#'}
        ]
        for item in permission_list:
            regex = '^%s$' % item['url']
            if re.match(regex, current_path):
                has_permission = True
                request.current_selected_permission = item['pid'] or item['id']
                if not item['pid']:  # 选中的是二级菜单
                    url_record.extend([
                        {'title': item['title'], 'url': item['url'], 'class': 'active'}
                    ])
                else:  # 选中的是具体权限
                    url_record.extend([
                        {'title': item['p_title'], 'url': item['p_url']},
                        {'title': item['title'], 'url': item['url'], 'class': 'active'},
                    ])
                request.breadcrumb = url_record  # 通过request,把储存信息传给用户
                break

        if not has_permission:
            return HttpResponse('未获取权限')

当前选中二级菜单或具体权限会被加上class

 

三、模板处理

rbac/templatestag/rbac.py

import re
from collections import OrderedDict

from django.conf import settings
from django.template import Library

register = Library()

@register.inclusion_tag('rbac/breadcrumb.html')
def breadcrumb(request):
    return {'record_list': request.breadcrumb}

rbac/templates/rbac/breadcrumb.html

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

如果有class,就说明是被用户选中的二级菜单或url,反之,就给一个可以点击的a标签

在layout.html页面引入面包屑导航

    <div class="right-body">

        {% breadcrumb request %}  <!-- + -->

        {% block content %} {% endblock %}
    </div>

猜你喜欢

转载自www.cnblogs.com/lshedward/p/10497669.html