Django - 權限(5)- 非菜單權限對應的一級菜單展開、麪包屑導航

1、非菜單權限對應的一級菜單展開

  需求:客戶列表和帳單列表頁面中都有添加按鈕,當點擊添加客戶(或編輯客戶、刪除客戶)時,客戶列表所屬的一級菜單展開,當點擊添加帳單(或編輯帳單、刪除帳單)時,帳單列表所屬的一級菜單展開。html

一、permission表新增一個pid字段,表示非菜單權限的父級菜單權限id,permission模型類以下:django

class Permission(models.Model):
    """
    權限表
    """
    url = models.CharField(verbose_name='含正則的URL', max_length=32)
    title = models.CharField(verbose_name='標題', max_length=32)
    menu = models.ForeignKey(verbose_name='標題', to="Menu", on_delete=models.CASCADE, null=True)
    name = models.CharField(verbose_name='url別名', max_length=32, default="")
    pid = models.ForeignKey("self", on_delete=models.CASCADE, null=True, verbose_name='父權限')

    def __str__(self):
        return self.title

二、修改權限列表數據結構,注入session,setsession.py中代碼以下:session

def initial_session(user_obj, request):
    """
    將當前登陸人的全部權限url列表和
    本身構建的全部菜單權限字典和
    權限表name字段列表注入session
    :param user_obj: 當前登陸用戶對象
    :param request: 請求對象HttpRequest
    """
    # 查詢當前登陸人的全部權限列表
    ret = Role.objects.filter(user=user_obj).values('permissions__url',
                                                    'permissions__title',
                                                    'permissions__name',
                                                    'permissions__pk',
                                                    'permissions__pid',
                                            'permissions__menu__title',
                                                'permissions__menu__icon',
                                                'permissions__menu__id').distinct()
    permission_list = []
    permission_names = []
    permission_menu_dict = {}
    for item in ret:
        # 獲取用戶權限列表用於中間件中權限校驗,改變數據結構
        permission_list.append({
            'url':item['permissions__url'],
            'id':item['permissions__pk'],
            'pid':item['permissions__pid'],
            'title':item['permissions__title']
        })
        # 獲取權限表name字段用於動態顯示權限按鈕
        permission_names.append(item['permissions__name'])

        menu_pk = item['permissions__menu__id']
        if menu_pk:
            if menu_pk not in permission_menu_dict:
                permission_menu_dict[menu_pk] = {
                    "menu_title": item["permissions__menu__title"],
                    "menu_icon": item["permissions__menu__icon"],
                    "children": [
                        {
                            "title": item["permissions__title"],
                            "url": item["permissions__url"],
                 "pk": item["permissions__pk"]
                        }
                    ],
                }
            else:
                permission_menu_dict[menu_pk]["children"].append({
                    "title": item["permissions__title"],
                    "url": item["permissions__url"],
                })
    print('權限列表', permission_list)
    print('菜單權限', permission_menu_dict)
    # 將當前登陸人的權限列表注入session中
    request.session['permission_list'] = permission_list
    # 將權限表name字段列表注入session中
    request.session['permission_names'] = permission_names
    # 將當前登陸人的菜單權限字典注入session中
    request.session['permission_menu_dict'] = permission_menu_dict

三、因修改了權限列表的數據結構,因此中間件校驗權限也須要修改,中間件middlewares.py代碼以下:數據結構

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect, HttpResponse
import re
class PermissionMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        # 設置白名單放行
        for reg in ["/login/", "/admin/*"]:
            ret = re.search(reg, request.path)
            if ret:
                return None

        # 檢驗是否登陸
        user_id = request.session.get('user_id')
        if not user_id:
            return redirect('/login/')

        # 檢驗權限
        permission_list = request.session.get('permission_list')
        for item in permission_list:
            reg = '^%s$' % item["url"]
            ret = re.search(reg, request.path)
            if ret:
                show_id = item["pid"] or item["id"]
                request.show_id = show_id  # 給request對象添加一個屬性
                return None
        return HttpResponse('無權訪問')

四、修改my_tags.py文件,代碼以下:app

@register.inclusion_tag("menu.html")
def get_menu_styles(request):
    permission_menu_dict = request.session.get("permission_menu_dict")
    print("permission_menu_dict", permission_menu_dict)

    for val in permission_menu_dict.values():
        for item in val["children"]:
            val["class"] = "hide"
            # /customer/
            # /customer/edit/3
            if request.show_id == item["pk"]:
                val["class"] = ""

    return {"permission_menu_dict": permission_menu_dict}

總結:以前菜單權限和非菜單權限之間沒有關係,經過在權限表中添加pid字段,創建菜單權限和非菜單權限之間的關係,來控制訪問某一非菜單權限時,其對應的菜單權限展開。ide

2、麪包屑導航

  需求:實現麪包屑導航url

一、修改中間件,middlewares.py中代碼以下:spa

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect, HttpResponse
import re
class PermissionMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        # 設置白名單放行
        for reg in ["/login/", "/admin/*"]:
            ret = re.search(reg, request.path)
            if ret:
                return None

        # 檢驗是否登陸
        user_id = request.session.get('user_id')
        if not user_id:
            return redirect('/login/')

        # 檢驗權限
        permission_list = request.session.get('permission_list')

        # 路徑導航列表
        request.breadcrumb = [
            {
                "title": "首頁",
                "url": "/"
            },
        ]
        for item in permission_list:
            reg = '^%s$' % item["url"]
            ret = re.search(reg, request.path)
            if ret:
                show_id = item["pid"] or item["id"]
                request.show_id = show_id  # 給request對象添加一個屬性

                # 肯定麪包屑列表
                if item["pid"]:
                    ppermission = Permission.objects.filter(pk=item["pid"])
                                          .first()
                    request.breadcrumb.extend(
                        [{  # 父權限字典
                            "title": ppermission.title,
                            "url": ppermission.url
                        },
                        {  # 子權限字典
                            "title": item["title"],
                            "url": request.path
                        }]
                    )
                else:
                    request.breadcrumb.append(
                        {
                            "title": item["title"],
                            "url": item["url"]
                        }
                    )
                    
                return None

        return HttpResponse('無權訪問')

二、公共模板頁面base.html中麪包屑導航位置的代碼以下:code

<div>
    <ol class="breadcrumb no-radius no-margin">
       {% for item in request.breadcrumb %}
           <li><a href="{{ item.url }}">{{ item.title }}</a></li>
       {% endfor %}
    </ol>
</div>
相關文章
相關標籤/搜索