如何制作一個簡單的django權限組件
阿新 • • 發佈:2018-10-11
fec 直接 itl mixin model 簡單 ext reg dep
第一步:
新建一個app
第二步:目錄結構
第三步:代碼如下
第一步:寫models
from django.db import models # 定義一級菜單 class Menu(models.Model): title = models.CharField(max_length=32, unique=True) # 名稱 icon = models.CharField(max_length=32, null=True, blank=True) # 圖標代碼:可以為空 def __str__(self):models.py文件中內容return self.title # 定義權限 class Permission(models.Model): """ 權限表 """ title = models.CharField(verbose_name=‘標題‘, max_length=32) # 定義標題,動態生成時候,要用到 url = models.CharField(verbose_name=‘含正則的URL‘, max_length=128) # url地址 name = models.CharField(max_length=32, verbose_name=‘url別名‘, unique=True) # 每個url的別名,唯一,且不能為空 menu = models.ForeignKey(‘Menu‘, null=True, blank=True, verbose_name=‘一級菜單‘) # 關聯的一級菜單 prent = models.ForeignKey(‘Permission‘, null=True, blank=True, verbose_name=‘關聯列表‘) # 自己關聯自己中的某個列表要使用的 def __str__(self): return self.title class Role(models.Model):""" 角色 """ title = models.CharField(verbose_name=‘角色名稱‘, max_length=32) # 定義角色的名字 permissions = models.ManyToManyField(verbose_name=‘擁有的所有權限‘, to=‘Permission‘, blank=True) # 和權限多對多關系 def __str__(self): return self.title # 定義用戶 class UserInfo(models.Model): """ 用戶表 """ name = models.CharField(verbose_name=‘用戶名‘, max_length=32) # 賬號 password = models.CharField(verbose_name=‘密碼‘, max_length=64) # 密碼 email = models.CharField(verbose_name=‘郵箱‘, max_length=32) # 郵箱 roles = models.ManyToManyField(verbose_name=‘擁有的所有角色‘, to=‘Role‘, blank=True) # 多對多關聯角色表 def __str__(self): return self.name
第二步:寫server文件下的init_permission.py
from django.conf import settings # 獲取當前登錄用戶的所有權限 def init_permission(request, user): rbac_list = user.roles.filter(permissions__url__isnull=False).values( ‘permissions__id‘, # 獲取權限的id ‘permissions__url‘,# 獲取權限的url ‘permissions__title‘,# 獲取權限的名字 ‘permissions__name‘,# 獲取權限的別名 ‘permissions__prent_id‘,# 獲取關聯列表的id ‘permissions__prent__name‘,# 獲取關聯列表的別名 ‘permissions__menu_id‘,# 獲取一級菜單的id ‘permissions__menu__title‘,# 獲取一級菜單的名字 ‘permissions__menu__icon‘, # 獲取一級菜單的圖標代碼 ).distinct() # 去重 url_dict = {} # 該用戶所有的權限 menu_dic = {} # 根據權限生成的菜單 for i in rbac_list: # 循環所有篩選出來的內容 """ 用每個權限的別名做key, value是[ ‘url‘:權限的url, ‘id‘:每個權限的id, ‘pid‘:‘它所關聯權限的id‘, ‘title‘:‘它自己的標題‘, ‘pname‘:‘它所關聯權限的別名‘ ] """ url_dict[i[‘permissions__name‘]] = {‘url‘: i[‘permissions__url‘], ‘id‘:i[‘permissions__id‘], ‘pid‘:i[‘permissions__prent_id‘], ‘title‘:i[‘permissions__title‘], ‘pname‘:i[‘permissions__prent__name‘], } # 獲取一級菜單的id menu_id = i.get(‘permissions__menu_id‘) # 判斷如果沒有一級菜單的id就重新循環 if not menu_id: continue # 判斷一級菜單的id是否存在menu_dic這個字典裏 # 如果存在 if menu_id not in menu_dic: """ 結構: 一級菜單id = { ‘title‘:一級菜單的名稱 ‘icon‘:一級菜單的圖標代碼 ‘children‘:[{ ‘title‘:二級菜單的標題, ‘url‘:二級菜單的url ‘id‘:二級菜單的id }]} """ menu_dic[i[‘permissions__menu_id‘]] = { ‘title‘: i[‘permissions__menu__title‘], ‘icon‘: i[‘permissions__menu__icon‘], ‘children‘: [ {‘title‘: i[‘permissions__title‘], ‘url‘: i[‘permissions__url‘], ‘id‘:i[‘permissions__id‘] } ] } else: menu_dic[i[‘permissions__menu_id‘]][‘children‘].append({‘title‘: i[‘permissions__title‘], ‘url‘: i[‘permissions__url‘], ‘id‘: i[‘permissions_id‘] }) # 把篩選出來的該用戶所有權限和菜單結構全部存入到session中 # settings.PERMISSION_SESSION_KEY和settings.MENU_SESSION_KEY:自己在自己的settings文件中設置 request.session[settings.PERMISSION_SESSION_KEY] = url_dict request.session[settings.MENU_SESSION_KEY] = menu_dic權限相關的所有代碼
第三步:寫middlewear下的rbac.py
import re from django.conf import settings from django.shortcuts import HttpResponse from django.utils.deprecation import MiddlewareMixin # 中間件 class RbacPermissionMiddleware(MiddlewareMixin): def process_request(self, request): # 獲取當前訪問的地址 current_url = request.path_info # 循環判斷白名單,自己在settings設置自己的白名單 for i in settings.WITER_LIST: if re.match(‘^%s$‘%i, current_url): return # 獲取當前用戶權限 permissions_dict = request.session[settings.PERMISSION_SESSION_KEY] # 小菜單要使用 request.breadcrumb_list=[{‘title‘:‘首頁‘,‘url‘:‘/‘}] # 循環判斷 flag = False # 循環用戶的所有權限 for item in permissions_dict.values(): # 正則匹配 if re.match(item[‘url‘], current_url): # 匹配成功修改flag flag = True # 獲取id,父級id,父級url別名 id = item[‘id‘] pid = item[‘pid‘] pname = item[‘pname‘] # 判斷是否有父級id if pid: # 獲取父級id,在動態生成菜單時要用 request.current_menu_id = pid # 父級的url,title,和自己的url好和title request.breadcrumb_list.extend([ {‘url‘:permissions_dict[pname][‘url‘],‘title‘:permissions_dict[pname][‘title‘]}, {‘url‘:item[‘url‘],‘title‘:item[‘title‘]}, ]) else: # 獲取自己id,在動態生成菜單時要用 request.current_menu_id = id # 自己的url好和title request.breadcrumb_list.extend([ {‘url‘: item[‘url‘], ‘title‘: item[‘title‘]} ]) break # 判斷當前用戶是否有權限訪問這個頁面 if not flag: return HttpResponse(‘你沒有此權限‘)中間件的代碼
第四步:寫templatetags下的rbac.py
from django.conf import settings from django import template from collections import OrderedDict register = template.Library() # 設置左側菜單的模板組件 @register.inclusion_tag(‘rbac/module.html‘) def show_results(request): # 獲取存儲菜單的字典 menu_dic = request.session[settings.MENU_SESSION_KEY] # 讓字典變的有序,python3.6在一些特殊的情況下會變得無序 order_dict = OrderedDict() # 循環這個字典,字典先排序 for item in sorted(menu_dic): # 把這個字典裏所有內容傳入到有序字典裏 order_dict[item] = menu_dic[item] # 給所有的一級菜單中都加入一個hide(隱藏) order_dict[item][‘class‘] = ‘hide‘ # 循環這個字典的二級菜單 for i in order_dict[item][‘children‘]: # 判斷當前訪問的url的id是否是當前循環二級菜單的id if request.current_menu_id == i[‘id‘]: # 如果是的話,給他添加‘active‘和去除一級菜單的‘hide‘ i[‘class‘] = ‘active‘ order_dict[item][‘class‘] = ‘‘ # 把字典出入html文件裏 return {‘menu_dic‘: order_dict} # 設置小菜單 @register.inclusion_tag(‘rbac/breadcrumb.html‘) def breadcrumb(request): # 把小菜單需要的列表傳入 return {‘breadcrumb_list‘: request.breadcrumb_list} # 設置過濾器 @register.filter def has_permission(request, name): # 判斷傳入的url別名是否在菜單字典中 if name in request.session.get(settings.PERMISSION_SESSION_KEY): return True標簽代碼
<div class="multi-menu"> {% for item in menu_dic.values %} <div class="item"> <div class="title"> <span class="icon-wrap"><i class="fa {{ item.icon }}"></i></span>{{ item.title }} </div> <div class="body {{ item.class }}"> {% for per in item.children %} <a href="{{ per.url }}" class="{{ per.class }}" >{{ per.title }}</a> {% endfor %} </div> </div> {% endfor %} </div>module.html的代碼
<ol class="breadcrumb no-radius no-margin" style="border-bottom: 1px solid #ddd;"> {% for item in breadcrumb_list %} {% if forloop.last %} <li class="active">{{ item.title }}</li> {% else %} <li><a href="{{ item.url }}">{{ item.title }}</a></li> {% endif %} {% endfor %} </ol>breadcrumb.html的代碼
第五步:admin.py中的代碼
from django.contrib import admin from rbac import models class PermissionAdmin(admin.ModelAdmin): list_display = [‘title‘, ‘url‘,‘menu‘,‘prent‘,‘name‘] # 頁面要顯示的內容 list_editable = [‘url‘,‘menu‘,‘prent‘,‘name‘] # 可以在頁面更改的內容 admin.site.register(models.Role) admin.site.register(models.Permission, PermissionAdmin) admin.site.register(models.UserInfo) admin.site.register(models.Menu)admin.py中的代碼
有一些註釋可能寫的比較迷,直接貼圖吧
左菜單/大菜單
小菜單
簡單的組件寫完了,組件的css和js代碼根據自己設計的頁面來寫
組件的使用
第一步:
如何制作一個簡單的django權限組件