3 權限粒度控制到按鈕
不同用戶登錄系統時候,根據權限不同來控制是否限制指定按鈕
第一步:修改表結構
class Permission(models.Model):
"""
權限表
"""
title = models.CharField(verbose_name='標題', max_length=32)
url = models.CharField(verbose_name='含正則的URL', max_length=128)
name = models.CharField(verbose_name="URL別名", max_length=32, unique=True)
menu = models.ForeignKey(verbose_name='所屬菜單', to='Menu', null=True, blank=True, help_text='null表示不是菜單;非null表示是二級菜單',
on_delete=models.CASCADE)
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

第二步:修改初始化信息
init_permission.py
from django.conf import settings
def init_permission(current_user, request):
"""
用戶權限信息的初始化
:param current_user:當前用戶對象
:param request:當前用戶的請求數據
:return:
"""
# 根據當前用戶信息獲取此用戶擁有的所有權限
permission_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", ).distinct()
# 獲取權限+菜單信息,寫入session
menu_dict = {}
permissions_dict = {}
for item in permission_queryset:
permissions_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
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, ]
}
request.session[settings.PERMISSION_SESSION_KEY] = permissions_dict
request.session[settings.MENU_SESSION_KEY] = menu_dict
第三步:修改中間件
rbac.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
from django.conf import settings
class RbacMiddleware(MiddlewareMixin):
"""
用戶權限信息校驗
"""
def process_request(self, request):
"""
當用戶請求剛進入時候出發執行
:param request:
:return:
"""
"""
1. 獲取當前用戶請求的URL
2. 獲取當前用戶在session中保存的權限列表 ['/customer/list/','/customer/list/(?P<cid>\\d+)/']
3. 權限信息匹配
"""
current_url = request.path_info
for valid_url in settings.VALID_URL_LIST:
if re.match(valid_url, current_url):
# 白名單中的URL無需權限驗證即可訪問
return None
permission_dict = request.session.get(settings.PERMISSION_SESSION_KEY)
if not permission_dict:
return HttpResponse('未獲取到用戶權限信息,請登錄!')
flag = False
url_record = [
{"title": "首頁", "url": "#"}
]
for item in permission_dict.values():
reg = "^%s$" % item["url"]
if re.match(reg, current_url):
flag = 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.url_record = url_record
break
if not flag:
return HttpResponse('無權訪問')
第四步:filter過濾
rbac.py
from django.template import Library
from django.conf import settings
register = Library()
@register.filter
def has_permission(request, name):
"""最多只能傳2個參數,做權限過濾"""
if name in request.session[settings.PERMISSION_SESSION_KEY]:
return True
第五步:模板應用
customer_list.html
{% extends 'layout.html' %}
{% load rbac %}
{% block content %}
<div class="luffy-container">
<div class="btn-group" style="margin: 5px 0">
{% 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 %}
</div>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>ID</th>
<th>客戶姓名</th>
<th>年齡</th>
<th>郵箱</th>
<th>公司</th>
{% if request|has_permission:"customer_del" or request|has_permission:"customer_edit" %}
<th>選項</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for row in data_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td>{{ row.age }}</td>
<td>{{ row.email }}</td>
<td>{{ row.company }}</td>
{% if request|has_permission:"customer_del" or request|has_permission:"customer_edit" %}
<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 %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
權限粒度控制到按鈕代碼下載

浙公網安備 33010602011771號