Django权限机制
Model Permissions
Django原生权限机制基于Model实现,对于每个Model而言,系统将自动添加add、change和delete这三个权限。
自定义的权限需要在model中手动添加:
每个权限包含
- content_type 对应该权限作用的模型,既Token。
- code_name 对应该权限功能,既view_token,在检查权限时会使用。
- name 对应该权限功能的描述,既Can see token。
自定义权限使用代码新建:
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get_for_model(Token)
permission = Permission.objects.create(codename='view_token',
name='Can see token',
content_type=content_type)
print(request.user.has_perm('user.add_token')) # 检查用户是否拥有某项权限 has_perm(app_name.permission_codename)
permission = Permission.objects.get(codename='add_token') # 获取权限实例
request.user.user_permissions.add(permission) # 为用户新增权限
print(request.user.get_all_permissions()) # 查看用户全部权限
# 由于权限缓存机制 用户的权限在第一次获取用户实例时会被缓存下来
# 为用户增加了权限后不会立即更新 若想立即查询用户的新的权限状态
# 需要重新获取用户实例 详见:djangoproject-permission-caching
user = User.objects.get(pk=request.user.id)
print(user.has_perm('user.add_token')) # 立即检查新权限添加状态
user.user_permissions.remove(permission) # 为用户删除权限
request.user.user_permissions.clear() # 清除用户全部权限
http://blog.igevin.info/posts/django-permission/
https://docs.djangoproject.com/en/1.10/ref/contrib/auth/
Group Permission
Group Permission的管理机制基本上和Moedl Permission一直,基本方法如下:
group.permissions.set([permission_list])
group.permissions.add(permission, permission, ...)
group.permissions.remove(permission, permission, ...)
group.permissions.clear()
权限检查依旧使用model.has_permission()方法。
new_group, created = Group.objects.get_or_create(name='new_group')
new_group.permissions.add(permission)
request.user.groups.add(new_group)
DRF中自定义权限检查
# override GET /user/
# 查看用户列表
def list(self, request, *args, **kwargs):
permission_required(request.user, ['user.view_user'])
users = User.objects.all()
serializer = UserListSerializer(users, many=True)
return Response(serializer.data)
from rest_framework.exceptions import PermissionDenied, MethodNotAllowed
from .models import *
# 获取某个model的全部权限列表
# Receive ----------------------------------
# model: a model
# Return -----------------------------------
# permissions: all permission related to this model
def get_model_permission(model):
content_type = ContentType.objects.get_for_model(model)
permissions = Permission.objects.filter(content_type=content_type)
return permissions
def permission_required(user, perm_list):
if user.has_perms(perm_list):
pass
else:
raise PermissionDenied
def list(self, request, *args, **kwargs):
self.add_log(request=request)
permission_list = []
import django.apps
for model in django.apps.apps.get_models(): # 获取所有的model
data = {}
content_type = ContentType.objects.get_for_model(model) # 获取model对应的content_type
permissions = Permission.objects.filter(content_type=content_type) # 获取该model的所有permission
serializer = self.get_serializer(permissions, many=True) # 序列化
data['name'] = str(model._meta.verbose_name) # 压入json中
data['content_type'] = str(content_type.id)
data['permissions'] = serializer.data
permission_list.append(data) # json压入list中
# 将list按照json中的content_type正序排列
# 不加int(x['content_type])将按照str类型排序 顺序:1 10 11... 2 20
# reverse 反序
permission_list = sorted(permission_list, key=lambda x: int(x['content_type']), reverse=False)
return success_response(permission_list)
from rest_framework.permissions import IsAdminUser
class IsVbAdminUser(IsAdminUser):
"""
Allows access only to admin users.
"""
def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return self.has_permission(request, view)
然后在 viewset 中,例如获取详情接口,这样用,
superuser在所有权限检测has_perm均返回True