Kingfan1993

权限粒度实现

修改表结构

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 %}

思路总结

  1. 给权限表添加action字段,目的是处理‘/user/delete(\d+)’这种url的匹配问题,相当于起别名
    2.给权限分组,便于定位到权限属于哪一组,可以理解是对那张表进行增删改查
    3.权限粒度,判断按钮是否需要显示。

分类:

技术点:

相关文章: