下面来定义自己的权限 并应用在自己的页面上呢?
首先要说的是,我们必须为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>