下面來定義自己的權限 並應用在自己的頁面上呢?
首先要說的是,我們必須為url設置name, 因為權限需要和urlname配合使用,urlname就是url(r’’, views.method, name=’urlname’)里的name值。還要建立權限名稱和具體操作的映射關系, 即權限名稱與(urlname, 請求方法,參數列表)的對應關系,如果用字典表示,就是這樣的:
{'add student', 'get', []}
第一步,要在models中建立權限的名稱和描述信息,這個信息是在django admin中設置權限時顯示的信息
第二步,建立一個權限表Permission, 將權限的名稱,url名稱,請求方法(get or post), 參數列表保存進去
第三步, 定義判斷權限的方法
下面來實驗一下,我們定義一個查看學員列表的權限:
第一步: 在models中建立權限表,我是將映射關系存放在數據庫中:
class Permission(models.Model): name = models.CharField("權限名稱", max_length=64) url = models.CharField('URL名稱', max_length=255) chioces = ((1, 'GET'), (2, 'POST')) per_method = models.SmallIntegerField('請求方法', choices=chioces, default=1) argument_list = models.CharField('參數列表', max_length=255, help_text='多個參數之間用英文半角逗號隔開', blank=True, null=True) describe = models.CharField('描述', max_length=255) def __str__(self): return self.name class Meta: verbose_name = '權限表' verbose_name_plural = verbose_name #權限信息,這里定義的權限的名字,后面是描述信息,描述信息是在django admin中顯示權限用的 permissions = ( ('views_notice_list', '查看notice'), ('views_notice_create', '創建notice'), )
重要第二步:在權限表中添加內容,將對應權限寫入數據庫:這里要注意
權限名稱可以通過打印方式獲取 如果想要給誰加某些權限就可以參考以次方法打印出來的權限的名稱
如當前以root的身份登陸 print(request.user.get_all_permissions())#查看用戶的所有權限==== #打印信息如下 {'notice.delete_permission', 'auth.add_group', 'notice.add_notice', 'notice.delete_detailcontent', 'notice.add_detailcontent', 'auth.view_group',
'admin.change_logentry', 'notice.view_permission', 'accounts.change_myuser', 'notice.views_notice_list', 'auth.change_group',
'notice.add_permission', 'auth.delete_group', 'sessions.change_session', 'admin.add_logentry', 'notice.delete_notice', 'notice.view_detailcontent',
'accounts.view_myuser', 'contenttypes.change_contenttype', 'admin.view_logentry', 'auth.delete_permission', 'notice.change_detailcontent',
'admin.delete_logentry', 'notice.views_notice_create', 'accounts.delete_myuser', 'auth.change_permission', 'contenttypes.view_contenttype',
'sessions.delete_session', 'notice.change_permission', 'contenttypes.delete_contenttype', 'auth.add_permission', 'sessions.add_session',
'contenttypes.add_contenttype', 'sessions.view_session', 'notice.view_notice', 'auth.view_permission', 'accounts.add_myuser', 'notice.change_notice'}
urls.py

urlpatterns = [
path('login/', views.log_in),
path('signup/', views.sign_up),
]
登陸頁相關的配置
login.html 登陸

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/accounts/login/" method="post"> <p>用戶名: <input type="text" name="user"></p> <p>密碼: <input type="password" name="pwd"></p> <p><input type="submit"></p> </form> </body> </html>
sign_up.html 注冊

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/accounts/signup/" method="post"> <p>用戶名: <input type="text" name="user"></p> <p>密碼: <input type="password" name="pwd1"></p> <p>確認密碼: <input type="password" name="pwd2"></p> <p>手機號: <input type="text" name="phone"></p> <p><input type="submit"></p> </form> </body> </html>
登陸注冊函數 這個函數中都是用到的
from django.contrib import auth
中的auth,實現用戶登陸,記錄用戶的session
views.py

from django.shortcuts import render,redirect,HttpResponse from django.contrib import auth # Create your views here. from accounts.models import MyUser def log_in(request): if request.method=="POST": username=request.POST['user'] password=request.POST['pwd'] print(username,password,'zheshi dengl xixni========') user = auth.authenticate(username=username,password=password) if user: #設置session內部的字典內容 auth.login(request,user) #登錄成功就將url重定向到后台的url return HttpResponse('登陸成功') else: return redirect('/accounts/login/') #登錄不成功或第一訪問就停留在登錄頁面 return render(request,'login.html') def sign_up(request): state = None if request.method == 'POST': password = request.POST.get('pwd1', '') repeat_password = request.POST.get('pwd2', '') phone = request.POST.get('phone', '') username = request.POST.get('user', '') if MyUser.objects.filter(username=username): state = 'user_exist' else: if password == repeat_password: new_user = MyUser.objects.create_user(username=username, password=password, phone=phone) new_user.save() return HttpResponse('成功') # return redirect('/book/') state = '密碼兩次不一致' content = { 'state': state, 'user': None,} return render(request, 'sign_up.html', content)
第三步: 定義權限驗證方法, 邏輯是這樣,請求訪問學員列表, 先獲取url地址,根據url地址得到urlname, 再獲取請求方法和參數,然后使用urlname, 請求方法,參數列表到數據庫中查詢,能查詢到之后說明這個權限存在;然后再使用request.user.has_perm()來判斷該用戶是否具有該權限。
在應用school目錄下建立permission.py文件,我們將權限驗證方法寫在這里面:
from django.shortcuts import render from notice import models from django.db.models import Q from django.urls import resolve #此方法可以將url地址轉換成url的name def perm_check(request, *args, **kwargs): url_obj = resolve(request.path_info) url_name = url_obj.url_name perm_name = '' #權限必須和urlname配合使得 if url_name: #獲取請求方法,和請求參數 url_method, url_args = request.method, request.GET url_args_list = [] #將各個參數的值用逗號隔開組成字符串,因為數據庫中是這樣存的 for i in url_args: url_args_list.append(str(url_args[i])) url_args_list = ','.join(url_args_list) if not url_args_list: url_args_list = None #操作數據庫 method_dic = {'GET':1,'POST':2} # print(request.user.get_all_permissions())#查看用戶的所有權限==== #根據當前請求頭的參數 如 url method 和參數來獲取當前的請求定義的權限對象 get_perm = models.Permission.objects.filter(url=url_name,per_method=method_dic[url_method]) if get_perm: #如果存在這個權限對象,則重點是獲取這個權限的name信息, for i in get_perm: perm_name = i.name #這個權限的名稱一定要跟權限表中要控制的權限名稱一致, perm_str = 'notice.%s' % perm_name #這樣拼接出權限的名稱,前邊是表的名稱 . 后邊是權限的操作內容 #然后去用戶的所有權限中去查看是否擁有此權限 if request.user.has_perm(perm_str): print('====》權限已匹配') return True else: print('---->權限沒有匹配') return False else: return False else: return False #沒有權限設置,默認不放過 def check_permission(fun): #定義一個裝飾器,在views中應用 def wapper(request, *args, **kwargs): if perm_check(request, *args, **kwargs): #調用上面的權限驗證方法 return fun(request, *args, **kwargs) return render(request, '403.html', locals()) return wapper
到這里自定義權限已經完成了,接下來要做的是在我們自己的頁面中使用:
創建一個student_list.html頁面,展示學員列表:
創建views方法:
我們使用裝飾器的方法來檢查權限。當用戶具有權限時,返回渲染的頁面。但似乎還少了點什么,在權限驗證方法里,當檢測沒有權限時返加403頁面,所以我們還要創建一個403頁面403.html:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>403</h1> <h2>You don't have enought permissions to this action!</h2> </body> </html>