我们知道在创建了一个 Django 项目之后,默认就有两个公开可用的 model:User 和 Group,这两个 model 的一项功能就是用来做权限管理的。系统中会有很多项权限,单个 user 可以配置拥有哪些权限,也可以将权限配置给 group。然后校验单个权限的时候其实就是将 user 本身的权限,和 user 所在的所有组的权限做一个并集,看本次操作的权限是否在这个并集里。在,那就校验通过;不在,那就只有 HTTP 403 了。
Django 自己对每一个 model 都创建了 create,update,delete 的权限,我们可以直接拿来用,也可以自己添加新权限。Django 自己是针对各个 model 做的权限,所以最简单的权限建立是在 model 层进行的。就比如下面这种,如果我想要为 Student 这个 model 建立相关的权限,就可以通过修改 Meta 类里的 permissions 来实现。
defhas_perm(self, perm, obj=None): """ Return True if the user has the specified permission. Query all available auth backends, but return immediately if any backend returns True. Thus, a user who has permission from a single auth backend is assumed to have permission in general. If an object is provided, check permissions for that object. """ # Active superusers have all permissions. if self.is_active and self.is_superuser: returnTrue
# Otherwise we need to check the backends. return _user_has_perm(self, perm, obj)
defhas_perms(self, perm_list, obj=None): """ Return True if the user has each of the specified permissions. If object is passed, check if the user has all required perms for it. """ returnall(self.has_perm(perm, obj) for perm in perm_list)
然后要考虑的就是如何将权限分给用户了,我们可以在 Django 源码中看到 user 和 permission 的关联关系是:ManyToMany ,所以直接修改用户的user_permissions字段就可以了。针对 group 也是一样的。
1 2 3 4 5 6 7 8 9 10
In [36]: shawn = User.objects.get(username='shawn')
In [37]: perm = Permission.objects.get(codename='add_user')
In [38]: shawn.user_permissions.add(perm)
In [39]: shawn.save()
In [40]: shawn.has_perm('auth.add_user') Out[40]: True
classAPIView(View): permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES # ......... defget_permissions(self): """ Instantiates and returns the list of permissions that this view requires. """ return [permission() for permission in self.permission_classes] defcheck_permissions(self, request): """ Check if the request should be permitted. Raises an appropriate exception if the request is not permitted. """ for permission in self.get_permissions(): ifnot permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'message', None) )
defcheck_object_permissions(self, request, obj): """ Check if the request should be permitted for a given object. Raises an appropriate exception if the request is not permitted. """ for permission in self.get_permissions(): ifnot permission.has_object_permission(request, self, obj): self.permission_denied( request, message=getattr(permission, 'message', None) )