Django--权限信息操作
一 . 权限控制
表结构的设计
rbca(Role Based Access Control) 基于角色的权限控制
3个model 5张表
class User(models.Model): # 用户表 username = models.CharField(max_length=16) password = models.CharField(max_length=16) # 多对多的外键一般写在查询方便的那一边 roles = models.ManyToManyField('Role', verbose_name='用户和角色关系表',blank=True) class Role(models.Model): # 角色表 username = models.CharField('角色',max_length=16) permissions = models.ManyToManyField('Permission', verbose_name='角色和权限关系表', blank=True) class Permission(models.Model): # 权限表 url = models.CharField('权限', max_length=64) title = models.CharField('标题', max_length=16)
# 权限表里面的url一定要加上 / / , 这样用正则的时候才能匹配成功
二 . 在admin中对表进行操作
# 创建超级用户的命令 python manage.py createsuperuser # 然后在admin文件中创建表 from django.contrib import admin admin.site.register(models.Permission) admin.site.register(models.User) admin.site.register(models.Role
登录admin,样式不是我们想要的,我们需要进行一下操作
然后在admin中写上:
修改之后的结果
还可以在展示页面上直接对字段进行编辑
展示结果
三 . 权限控制的流程
其实我们控制权限的实质就是让某些人能访问特定的url
我们需要把权限控制的验证写到中间件中去
# 视图函数 def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') obj = models.User.objects.filter(username=username, password=password).first() if not obj: return render(request, 'login.html', {'error': '用户名或密码错误'}) # 跨表查询用双下划线 ORM获取到权限信息 过滤掉权限为空的 去重 permission_query = obj.roles.filter(permissions__url__isnull=False).values('permissions__url', 'permissions__title').distinct() # session的值需要是可序列化的, 需要把QuerySet变成列表 request.session['permission'] = list(permission_query) request.session['is_login'] = True return redirect('index') return render(request,'login.html')
# 权限验证中间件 1 from django.utils.deprecation import MiddlewareMixin 2 from django.shortcuts import HttpResponse, redirect 3 from django.conf import settings 4 import re 5 class RbacMiddleWare(MiddlewareMixin): 6 def process_request(self,request): 7 # 获取当前访问的页面 8 url = request.path 9 10 # 白名单 11 for i in settings.WHITE_LIST: 12 # match 匹配上得到一个对象,匹配不上返回None 13 if re.match(i, url): 14 return 15 # 获取登录状态 16 is_login = request.session['is_login'] 17 # 没有登录跳转登录页面 18 if not is_login: 19 return redirect('login') 20 21 # 免认证 22 for i in settings.NO_PERMISSION_LIST: 23 # match 匹配上得到一个对象,匹配不上返回None 24 if re.match(i, url): 25 return 26 27 # 获取当前用户的权限, 要用get去拿,没有显示None,[]就会报错 28 permission_list = request.session.get('permission') 29 # print(permission_list) 30 # 权限的校验 31 for permission in permission_list: 32 # print('>>>>',permission) 33 if re.match(f'^{permission["permissions__url"]}$', url): 34 return 35 # 没有匹配成功 36 return HttpResponse('你的level不够!!')
我们在其他py文件中引入settings的时候,要用以下方式
from django.conf import settings