权限粒度实现
修改表结构
from django.db import models
# Create your models here.
# 用户表多对多关联角色表
class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
roles = models.ManyToManyField(to=\'Role\')
class Meta:
verbose_name=\'用户\'
verbose_name_plural=verbose_name
def __str__(self):
return self.name
# 角色表,多对多关联权限表
class Role(models.Model):
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(to=\'Permission\')
class Meta:
verbose_name=\'角色\'
verbose_name_plural=verbose_name
def __str__(self):
return self.title
# 权限表,每个权限对应一个实际要访问的url
class Permission(models.Model):
title = models.CharField(max_length=32)
url = models.CharField(max_length=32)
action = models.CharField(max_length=32,null=True)
group = models.ForeignKey(to=\'PermissionGroup\',null=True)
class Meta:
verbose_name=\'权限\'
verbose_name_plural=verbose_name
def __str__(self):
return self.title
class PermissionGroup(models.Model):
title = models.CharField(max_length=32)
class Meta:
verbose_name=\'权限组\'
verbose_name_plural=verbose_name
def __str__(self):
return self.title
增加url的action字段目的是为了更方便的去定位url,增加权限组表,便于定位到哪个组下面的权限
创建数据结构
# permisson_dict = {
# \'权限组id1\':{
# \'url\':[\'/user/\',\'/user/add/\',\'/user/delet/(\d+)\'],
# \'action\':[\'list\',\'add\',\'delet\']
# },
# \'权限组id2\':{
# \'url\':[\'/book/\',\'/book/add/\',\'/book/delet/(\d+)\'],
# \'action\':[\'list\',\'add\',\'delet\']
# },
# }
重新修改登录视图和权限判断中间件
登录视图
def login(request):
if request.method==\'POST\':
# 获取登录后要跳转的下一页
next_url = request.GET.get(\'next\',\'/login\')
# 获取账号密码
user = request.POST.get(\'user\', \'\')
pwd = request.POST.get(\'pwd\', \'\')
user_obj = User.objects.filter(name=user, pwd=pwd)
if user_obj:
permission_list = user_obj.values(\'roles__permissions__url\',\'roles__permissions__action\'
,\'roles__permissions__group_id\').distinct()
permission_dict = {}
for item in permission_list:
if item[\'roles__permissions__group_id\'] not in permission_dict:
permission_dict[item[\'roles__permissions__group_id\']] = {
\'url\':[item[\'roles__permissions__url\']],
\'action\':[item[\'roles__permissions__action\']]
}
else:
permission_dict[item[\'roles__permissions__group_id\']][\'url\'].append(item[\'roles__permissions__url\'])
permission_dict[item[\'roles__permissions__group_id\']][\'action\'].append(item[\'roles__permissions__action\'])
request.session[\'permission_dict\'] = permission_dict
return redirect(\'/index\')
return render(request,\'login.html\')
中间件
def process_request(self, request):
# 白名单url
wirte_url = [\'/login/\', \'/logout/\',\'/admin/.*\']
# 获取当前的url
current_url = request.path_info
# 如果当前请求的url是白名单的url直接放行:
for url in wirte_url:
print(222)
if re.match(r\'^{}$\'.format(url), current_url):
print(111)
return
# 否则判断当前请求url是否在当前登录的用户的权限url中
# 获取session中保存的用户权限url表
print(22332)
permission_dict = request.session.get(\'permission_dict\', {})
print(permission_dict)
for item in permission_dict.values():
for url in item[\'url\']:
if re.match(r\'^{}$\'.format(url), current_url):
print(\'中间件\',url)
print(\'中间件\',item[\'action\'])
# 将当期权限组下的所有权限别名添加到request属性中
request.action = item[\'action\']
return
return HttpResponse(\'没有权限\')
实现权限粒度
视图
# 封装对按钮的判断
class Button:
def __init__(self,action):
self.action = action
def add(self):
return \'add\' in self.action
def edit(self):
return \'edit\' in self.action
def register(reqeust):
return HttpResponse(\'注册\')
def index(reqeust):
obj = Button(reqeust.action)
return render(reqeust,\'base.html\',locals())
html按钮,调用button类的方法
{% if obj.edit %}
<a href="" class="btn-success btn">编辑用户</a>
{% endif %}
思路总结
- 给权限表添加action字段,目的是处理‘/user/delete(\d+)’这种url的匹配问题,相当于起别名
2.给权限分组,便于定位到权限属于哪一组,可以理解是对那张表进行增删改查
3.权限粒度,判断按钮是否需要显示。