權限組件(5):權限粒度控制到按鈕


效果圖:

 一、models層給權限增加url的別名

這是做是為了在模板用別名判斷當前用戶是否有這個url(權限)
rbac/models.py

class Permission(models.Model):
    """
    權限表
    """
    title = models.CharField(verbose_name='標題', max_length=32)
    url = models.CharField(verbose_name='含正則的URL', max_length=128)

    menu = models.ForeignKey(verbose_name='所屬菜單', to=Menu, null=True, blank=True,
                             help_text='null表示不是菜單,非null表示是二級菜單', on_delete=models.CASCADE
                             )

    name = models.CharField(verbose_name='url的別名', max_length=32, unique=True)  # +

    pid = models.ForeignKey(verbose_name='關聯的權限', to='Permission', null=True, blank=True, related_name='parents',
                            help_text='對於非菜單權限需要選擇一個可以成為菜單的權限,用於做默認展開和選中菜單',
                            on_delete=models.CASCADE
                            )

    def __str__(self):
        return self.title

 

注意:剛創建的時候設置成null=True和blank=True,當添加完數據后再設置unique=True,並刪除null=True和blank=True

二、在初始化權限中增加別名

把用戶權限以字典的形式儲存,別名作為key。values還是一個字典,儲存其他信息。
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__name',
        'permissions__pid_id',
        'permissions__pid__title',  # +
        'permissions__pid__url',
        'permissions__menu_id',
        'permissions__menu__title',
        'permissions__menu__icon',
    )

    permission_dict = {}  # + 

    menu_dict = {}

    for item in permission_menu_queryset:
        permission_dict[item['permissions__name']] = {
            '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_dict
    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_dict = request.session.get(settings.PERMISSION_SESSION_KEY)

       if not permission_dict:
           return HttpResponse('請先登錄 ')

       has_permission = False

       url_record = [
           {'title': '首頁', 'url': '#'}
       ]
       for item in permission_dict.values():
           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('未獲取權限,請先獲取權限')
 
        

四、模板處理

在templatestag里判斷用戶是否有權限(是否有url的別名)
rbac/templatestag/rbac.py

@register.filter()
def has_permission(request, name):
    """判斷是否有權限"""

    if name in request.session[settings.PERMISSION_SESSION_KEY]:
        return True

 

在需要把權限控制到按鈕的模板傳入request,和url的別名,並進行判斷。這里拿用戶列表舉例
業務app/templates/customer_list.html

{% extends 'layout.html' %}
{% load rbac %}   <!-- 系統會默認找到templatetags的文件下面的rbac模塊 -->
...
 {% if request|has_permission:'customer_add' %}
    <a class="btn btn-default" href="/customer/add/">
         <i class="fa fa-plus-square" aria-hidden="true"></i> 添加客戶
     </a>
{% endif %}

 {% if request|has_permission:'customer_import' %}
    <a class="btn btn-default" href="/customer/import/">
        <i class="fa fa-file-excel-o" aria-hidden="true"></i> 批量導入
    </a>
{% endif %}

{% if request|has_permission:'customer_edit' or request|has_permission:'customer_del' %}
     <th>選項</th>
{% endif %}

{% if request|has_permission:'customer_edit' or request|has_permission:'customer_del' %}
    <td>
        {% if request|has_permission:'customer_edit' %}
            <a style="color: #333333;" href="/customer/edit/{{ row.id }}/">
                <i class="fa fa-edit" aria-hidden="true"></i>
            </a>
        {% endif %}
        {% if request|has_permission:'customer_del' %}
            |
            <a style="color: #d9534f;" href="/customer/del/{{ row.id }}/">
                <i class="fa fa-trash-o"></i>
            </a>
        {% endif %}
    </td>
{% endif %}
...

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM