ENV: 应用场景有一种场景, 要求为用户赋予一个角色, 基于角色(比如后管理员,总编, 编辑), 用户拥有相应的权限(比如管理员拥有所有权限, 总编可以增删改查, 编辑只能增改, 有些页面的按钮也只有某些角色才能查看), 角色可以任意添加, 每个角色的权限也可以任意设置 django 的权限系统django 默认的权限是基于 设计权限大多数的系统, 都会给用户赋予某个角色, 假如能针对用户的角色, 做权限控制,这个权限控制并不局限于对
User 是用户对象 Role: 角色表 UserRole 是用户角色关系对象 RolePermissions 是角色权限关系对象 因此, 需要创建三个
其他Model 如下 class Role(models.Model): '''角色表''' # e.g add_user role_code = models.CharField('role code', max_length=64, unique=True, help_text = '用户角色标识') # e.g 新增用户 role_name = models.CharField('role name', max_length=64, help_text = '用户角色名')class UserRole(models.Model): '''用户角色关系表''' user_id = models.IntegerField('user id', blank=False, help_text='用户id', unique=True) role_codes = models.CharField('role codes', blank=True, default=None, max_length=256, help_text='用户的角色codes')class RolePermission(models.Model): '''角色权限关系表''' role_code = models.CharField('role code', max_length=64, blank=False, help_text = '用户角色标识') pm_code = models.CharField('permission code', blank=False, max_length=64, help_text='权限code') class Meta: unique_together = ('role_code', 'pms_code') 其中
权限管理用户角色拥有哪些权限是在代码里定义好的, 比如: PMS_MAP = ( ('PM_ADD_USER', '新增用户'), ('PM_SET_MAIL', '编辑邮箱'), ...)
角色管理在定义好权限后, 我们就可以做角色管理了, 在这里, 我们可以创建任意的角色, 为其分配任意的权限, 当然, 最好创建有意义的角色 角色表单定义( role_regex_validator = RegexValidator(r'[a-zA-Z0-9]', '角色标记只能包含字母,数字, 下划线')class RoleForm(forms.Form): role_row_code = forms.IntegerField(required=False, widget=forms.HiddenInput()) role_code = forms.CharField(label='角色标记', min_length=3, max_length=64, validators=[role_regex_validator]) role_name = forms.CharField(label='角色名', min_length=3, max_length=64) OPTIONS = PMS_MAP pms = forms.MultipleChoiceField(label='权限列表', widget=forms.SelectMultiple(choices=OPTIONS) 角色编辑 def role_edit(request): '''角色编辑''' if request.method == 'POST': role_row_id = request.POST.get('role_row_id', 0) role_code = request.POST.get('role_code', '') role_name = request.POST.get('role_name', '') pms = request.POST.getlist('pms', []) # 表单校验 role_form = RoleForm({ 'role_row_id': role_row_id, 'role_code': role_code, 'role_name': role_name, 'pms': pms }) # 表单校验 if not role_form.is_valid(): return render(request, 'role_form.html', {'form': role_form) role_row_id = role_form.cleaned_data.get('role_row_id', None) if role_row_id: # 角色更新 return update_role(request, role_form, role_row_id=role_row_id, role_code=role_code, role_name=role_name, pms=pms) else: # 角色创建 return add_role(request, role_form, role_code, role_name, pms=pms) else: # 角色编辑页面 role_row_id = request.GET.get('id') try: role_item = Role.objects.get(pk=role_row_id) except Role.DoesNotExist as e: role_item = None if role_item: # 编辑已有角色表单 # 获取角色权限列表 role_pms_rows = RolePermission.objects.filter(role_code=role_item.role_code) pms_codes = [role_pms_row.pms_code for role_pms_row in role_pms_rows] role_form = RoleForm({ 'role_row_id': role_row_id, 'role_code': role_item.role_code, 'role_name': role_item.role_name, 'pms': pms_codes }) else: # 新增角色表单 role_form = RoleForm() return render(request, 'role_form.html', {'form': role_form})def add_role(request, role_form, role_code, role_name, pms=()): '''新增角色''' try: with transaction.atomic(): role_item = Role.objects.create(role_code=role_code, role_name=role_name) for pm_code in pms: RolePermission.objects.update_or_create(role_code=role_code, pms_code=pm_code) return redirect('{}?id={}'.format(reverse('user_role_edit'), role_item.pk)) except IntegrityError as e: # 创建出错 role_form.add_error('role_code', '角色已经存在: {}'.format(role_code)) return render(request, 'role_form.html', {'form': role_form})def update_role(request, role_form, role_row_id, role_code, role_name, pms=()): '''更新角色''' try: with transaction.atomic(): role_item = Role.objects.get(pk=role_row_id) # 校验合法性 if not role_item: raise Http404('非法的role记录id') role_item.role_name = role_name role_item.save() # 删除原角色权限设置 RolePermission.objects.filter(role_code=role_code).delete() for pm_code in pms: RolePermission.objects.update_or_create(role_code=role_code, pms_code=pm_code) return redirect('{}?id={}'.format(reverse('user_role_edit'), role_row_id)) except IntegrityError as e: # 更新出错 role_form.add_error('role_name', '更新角色名出错:{}'.format(role_name)) return render(request, 'role_form.html', {'form': role_form}) 表单部分html <form class='form-horizontal' action='/user/role/edit' method='POST'> <p>用户角色编辑p> {{form.non_field_errors}} {% csrf_token %} {% for hidden_field in form.hidden_fields %} {{ hidden_field }} {% endfor %} {% for field in form.visible_fields %} <div class='form-group'> <label class='col-lg-2 control-label'>{{field.label}}label> {% if field.errors %} <div class='col-lg-3 has-error'> {{field}} {% for error in field.errors %} <p><span class='help-block m-b-none'>{{error}}span><p> {% endfor %} div> {% else %} <div class='col-lg-3'> {{field}} div> {% endif%} div> {% endfor %} <div class='form-group'> <div class='col-lg-offset-2 col-lg-10'> <button class='btn btn-sm btn-white' type='submit'>Savebutton> div> div> form> 至此用户角色编辑就完成了 还有一部分是用户角色分配 说白了就是编辑用户时, 给用户选择一个角色, 将用户id和角色code 通过 权限判断如果我们有了一个用户, 并赋予了一个角色, 应该怎么判断其是否有某个权限呢 在django的认证体系配置里, 有一项配置是 AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', 'cas.backends.CASBackend', # 单点登录实现) 这个配置项下每个字符串都对应一个类, 每个类继承并了一组接口实现中的全部或其中一部分 这组接口定义了用户认证和授权的相关内容, 如下 authenticateget_user_permissionsget_group_permissionshas_perm... 其中 has_perm 就是直接判断是否拥有某个权限的接口 在 因此, 我们实现自己的 class PermBackend(ModelBackend): def has_perm(self, user_obj, pms_code, obj): if not user_obj.is_active: return False # 超级管理员拥有所有权限 if user_obj.is_superuser: return True try: user_roles_record = UserRole.objects.get(user_id=user_obj.pk) except UserRole.DoesNotExist as e: return False # 获取用户的角色(暂时是单个角色) user_roles = user_roles_record.role_codes.split(',') # 角色对应的权限集合 role_pms_rows = RolePermission.objects.filter(role_code__in=user_roles) pms_codes = [role_pms_row.pms_code for role_pms_row in role_pms_rows] # pms_code 是否在用户的权限code集合中 return pms_code in pms_codes 当然, 别忘了把 现在, 我们在views funcion的实现前添加 无论是任何地方, 只要定义唯一的 |
|