一.什么是權限
能做哪些事情,不能做哪些事情,可以做的權限
二.設計權限
思路:
web應用中,所謂的權限,其實就是一個用戶能夠訪問的url,通過對用戶訪問的url進行控制,從而實現對用戶權限的控制.
每個用戶代表不同的的角色,每個角色具有不同的權限.
一個用戶可以有多重角色,多個人也可以是一種角色(比如說一個公司可以有多個銷售),所以說,用戶與角色之間的關系是多對多的關系.
一個角色能夠擁有多個權限,一個權限也可以分配給多個角色;所以說角色和權限的關系也是多對多的關系.
三.權限實現
建立表關系
具體代碼如下:
from django.db import models class Menu(models.Model): title = models.CharField(max_length=32) icon = models.CharField(max_length=32) weight = models.IntegerField(default=1, verbose_name='權重') class Permission(models.Model): """ 權限表 """ title = models.CharField(max_length=32, verbose_name='標題') url = models.CharField(max_length=32, verbose_name='權限') menu = models.ForeignKey(to='Menu',on_delete=models.CASCADE,default=0,blank=True,null=True) pid = models.ForeignKey('self',on_delete=models.CASCADE,null=True,verbose_name='父權限') name = models.CharField(max_length=32, null=True, blank=True, unique=True) class Meta: verbose_name_plural = '權限表' verbose_name = '權限表' def __str__(self): return self.title class Role(models.Model): name = models.CharField(max_length=32, verbose_name='角色名稱') permissions = models.ManyToManyField(to='Permission', verbose_name='角色所擁有的權限', blank=True) def __str__(self): return self.name class User(models.Model): """ 用戶表 """ name = models.CharField(max_length=32, verbose_name='用戶名') password = models.CharField(max_length=32, verbose_name='密碼') roles = models.ManyToManyField(to='Role', verbose_name='用戶所擁有的角色', blank=True) def __str__(self): return self.name
獲取權限信息
每次當用戶一登錄是,就應該獲取當前的用戶所擁有的所有權限信息.
當然了首先需要構建的應該是當前用戶的權限列表中.構建出來之后將其存入到session中,以便於之后的權限校驗
這里還需要構造出我們創建菜單想要的數據結構,以便於之后創建二級菜單.
然后我們構建出來的菜單數據結構和權限列表如下所示:

permission_list[{ 'url': '/customer/', 'pid': None, 'title': '全部客戶', 'id': 1 }, { 'url': '/customers/list/', 'pid': None, 'title': '共有客戶', 'id': 2 }, { 'url': '/mycustomers/', 'pid': None, 'title': '我的客戶', 'id': 3 }, { 'url': '/consult_records/', 'pid': None, 'title': '客戶跟進記錄', 'id': 4 }, { 'url': '/customer/count/', 'pid': None, 'title': '客戶成單統計', 'id': 5 }, { 'url': '/enrollment/', 'pid': None, 'title': '報名情況', 'id': 6 }, { 'url': '/enrollment/add/', 'pid': 6, 'title': '添加報名記錄', 'id': 7 }, { 'url': '/enrollment/edit/(\\d+)', 'pid': 6, 'title': '修改報名記錄', 'id': 8 }, { 'url': '/ClassStudyRecord/list/', 'pid': None, 'title': '班級學習記錄', 'id': 9 }, { 'url': '/ClassStudyRecord/add/', 'pid': 9, 'title': '添加學習記錄', 'id': 10 }, { 'url': '/studentstudyrecord/edit/(\\d+)/', 'pid': 9, 'title': '添加記錄', 'id': 11 }, { 'url': '/rbac/role/list/', 'pid': None, 'title': '角色管理', 'id': 12 }, { 'url': '/rbac/role/add/', 'pid': 12, 'title': '添加角色', 'id': 13 }, { 'url': '/rbac/role/edit/(\\d+)', 'pid': 12, 'title': '修改角色', 'id': 14 }, { 'url': '/rbac/role/del/(\\d+)', 'pid': 12, 'title': '刪除角色', 'id': 15 }, { 'url': '/rbac/menu/list/', 'pid': None, 'title': '菜單管理', 'id': 16 }, { 'url': '/rbac/menu/add/', 'pid': 16, 'title': '添加目錄', 'id': 17 }, { 'url': '/rbac/menu/edit/(\\d+)', 'pid': 16, 'title': '修改目錄', 'id': 18 }, { 'url': '/rbac/permission/distrbute/', 'pid': None, 'title': '分配權限', 'id': 19 }, { 'url': '/rbac/permission/tree/', 'pid': 19, 'title': '權限樹', 'id': 20 }, { 'url': '/index/', 'pid': None, 'title': '首頁', 'id': 21 }, { 'url': '/logout/', 'pid': None, 'title': '注銷', 'id': 22 }, { 'url': '/customers/add/', 'pid': 1, 'title': '添加客戶', 'id': 23 }, { 'url': '/customers/add/', 'pid': 2, 'title': '添加客戶', 'id': 24 }, { 'url': '/customers/add/', 'pid': 3, 'title': '添加客戶', 'id': 25 }, { 'url': '/customer/del/(\\d+)/', 'pid': 1, 'title': '刪除客戶', 'id': 26 }, { 'url': '/customer/del/(\\d+)/', 'pid': 2, 'title': '刪除客戶', 'id': 27 }, { 'url': '/customer/del/(\\d+)/', 'pid': 3, 'title': '刪除客戶', 'id': 28 }, { 'url': '/customers/edit/(\\d+)', 'pid': 1, 'title': '修改客戶', 'id': 29 }, { 'url': '/customers/edit/(\\d+)', 'pid': 2, 'title': '修改客戶', 'id': 30 }, { 'url': '/customers/edit/(\\d+)', 'pid': 3, 'title': '修改客戶', 'id': 31 }, { 'url': '/consult_records/add/', 'pid': 4, 'title': '添加客戶跟進記錄', 'id': 32 }, { 'url': '/consult_records/(\\d+)', 'pid': 4, 'title': '修改客戶跟進記錄', 'id': 33 }, { 'url': '/del_consult/(\\d+)', 'pid': 4, 'title': '刪除客戶跟進記錄', 'id': 34 }]

permission_menu_dic { '2': { 'menu_title': '客戶管理', 'menu_icon': 'nav-icon fa fa-dashboard', 'childern': [{ 'title': '全部客戶', 'url': '/customer/' }, { 'title': '共有客戶', 'url': '/customers/list/' }, { 'title': '我的客戶', 'url': '/mycustomers/' }, { 'title': '客戶跟進記錄', 'url': '/consult_records/' }, { 'title': '客戶成單統計', 'url': '/customer/count/' }] }, '3': { 'menu_title': '報名管理', 'menu_icon': 'nav-icon fa fa-table', 'childern': [{ 'title': '報名情況', 'url': '/enrollment/' }] }, '4': { 'menu_title': '成績管理', 'menu_icon': 'nav-icon fa fa-th', 'childern': [{ 'title': '班級學習記錄', 'url': '/ClassStudyRecord/list/' }] }, '5': { 'menu_title': '權限管理', 'menu_icon': 'nav-icon fa fa-tree', 'childern': [{ 'title': '角色管理', 'url': '/rbac/role/list/' }, { 'title': '菜單管理', 'url': '/rbac/menu/list/' }, { 'title': '分配權限', 'url': '/rbac/permission/distrbute/' }] } } permission_menu_dic { '2': { 'menu_title': '客戶管理', 'menu_icon': 'nav-icon fa fa-dashboard', 'childern': [{ 'title': '全部客戶', 'url': '/customer/', 'active': 'active' }, { 'title': '共有客戶', 'url': '/customers/list/' }, { 'title': '我的客戶', 'url': '/mycustomers/' }, { 'title': '客戶跟進記錄', 'url': '/consult_records/' }, { 'title': '客戶成單統計', 'url': '/customer/count/' }], 'style': 'display:block', 'class': 'menu-open' }, '3': { 'menu_title': '報名管理', 'menu_icon': 'nav-icon fa fa-table', 'childern': [{ 'title': '報名情況', 'url': '/enrollment/' }] }, '4': { 'menu_title': '成績管理', 'menu_icon': 'nav-icon fa fa-th', 'childern': [{ 'title': '班級學習記錄', 'url': '/ClassStudyRecord/list/' }] }, '5': { 'menu_title': '權限管理', 'menu_icon': 'nav-icon fa fa-tree', 'childern': [{ 'title': '角色管理', 'url': '/rbac/role/list/' }, { 'title': '菜單管理', 'url': '/rbac/menu/list/' }, { 'title': '分配權限', 'url': '/rbac/permission/distrbute/' }] } }
具體構建代碼如下:
from rbac.models import Role def initial_sesson(user,request): """ 功能:將當前登錄人的所有權限錄入session中 :param user: 當前登錄人 """ # 查詢當前登錄人的所有權限列表 # 查看當前登錄人的所有角色 # ret=Role.objects.filter(user=user) permissions = Role.objects.filter(userinfo=user).values("permissions__url", "permissions__title", 'permissions__pid', 'permissions__pk', "permissions__menu__pk", "permissions__menu__title", "permissions__menu__icon", ).distinct() print('permissions',permissions) permission_list = [] permission_menu_dic = {} for item in permissions: # 構建權限列表 permission_list.append({ 'url':item["permissions__url"], 'pid':item["permissions__pid"], 'title':item["permissions__title"], 'id':item["permissions__pk"], }) # 構建菜單權限列表 if item["permissions__menu__pk"]: if not permission_menu_dic.get(item['permissions__menu__pk']): permission_menu_dic[item['permissions__menu__pk']] = { 'menu_title':item['permissions__menu__title'], 'menu_icon':item['permissions__menu__icon'], 'childern':[{ 'title':item['permissions__title'], 'url':item['permissions__url'] }] } else: permission_menu_dic[item['permissions__menu__pk']]['childern'].append({ 'title':item['permissions__title'], 'url':item['permissions__url'] }) print('permission_menu_dic',permission_menu_dic) # 將當前登錄人的權限列表注入session中 request.session["permission_list"] = permission_list # 將當前登錄人的菜單權限列表注入session中 print("permission_list",permission_list) request.session["permission_menu_dic"] = permission_menu_dic
構建菜單:
這里使用的django的自定義標簽incluSion_tags.
首先創建一個templatetags文件夾,(注意這個文件夾的名字必須是這個名字)
其次創建一個py文件,這個文件名可以隨意.
代碼如下:

from django.utils.safestring import mark_safe from django.template import Library import re register =Library() @register.inclusion_tag("rbac/menu.html") def get_menu_styles(request): permission_menu_dic = request.session.get("permission_menu_dic") print('permission_menu_dic',permission_menu_dic) for val in permission_menu_dic.values(): for item in val.get('childern'): if re.search('^{}$'.format(item['url']),request.path): val['style'] = 'display:block' val['class'] = 'menu-open' item['active'] = 'active' print("permission_menu_dic",permission_menu_dic) return {"permission_menu_dic":permission_menu_dic}
這里還需要一個菜單的模板:

{% for item in permission_menu_dic.values %} <li class="nav-item has-treeview {{ item.class }}"> <a href="#" class="nav-link"> <i class="{{ item.menu_icon }}"></i> <p> {{ item.menu_title }} <i class="right fa fa-angle-left"></i> </p> </a> <ul class="nav nav-treeview" style="{{ item.style }}"> {% for foo in item.childern %} <li class="nav-item"> <a href="{{ foo.url }}" class="nav-link {{ foo.active }}"> <i class="fa fa-circle-o nav-icon"></i> <p>{{ foo.title }}</p> </a> </li> {% endfor %} </ul> </li> {% endfor %}
這里的菜單css和js可以自己進行定制.我這里使用的是bootstrap的模板.
自此,菜單以及菜單權限就構建完成!