django admin 自定義權限驗證功能限定用戶訪問的url


 

 

下面來定義自己的權限 並應用在自己的頁面上呢?

首先要說的是,我們必須為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'),
        )

 

重要第二步:在權限表中添加內容,將對應權限寫入數據庫:這里要注意

image

 

 

 

權限名稱可以通過打印方式獲取   如果想要給誰加某些權限就可以參考以次方法打印出來的權限的名稱

如當前以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),
]
View Code

登陸頁相關的配置

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>
View Code

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>
View Code

 

登陸注冊函數  這個函數中都是用到的

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)
View Code

 

第三步: 定義權限驗證方法, 邏輯是這樣,請求訪問學員列表, 先獲取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方法:

from django.shortcuts import render,HttpResponse
from notice.permission import check_permission

# Create your views here.
from notice.models import Notice

@check_permission
def get_notice(request):
    notice_list = Notice.objects.all().first()
    print(notice_list.title)
    a = {}

    a['title'] = notice_list.title

    return render(request,'notice.html',a)


@check_permission
def creat_notice(request):
    if request.method == 'GET':
        return render(request,'create_notice.html',)
    title = request.POST.get('title',None)
    content = request.POST.get('content',None)
    if title and content:
        Notice.objects.create(title=title,content=content,)

        return HttpResponse('創建成功!!!')

@check_permission
def change_notice(request,**kwargs):
    id=kwargs.get('id')
    print(id,'這是id')
    return HttpResponse('創建成功!!!')

我們使用裝飾器的方法來檢查權限。當用戶具有權限時,返回渲染的頁面。但似乎還少了點什么,在權限驗證方法里,當檢測沒有權限時返加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>
View Code

 

 項目文件: 點我


免責聲明!

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



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