我认为其他回答都很好,但我们不应该直接压制在其装饰器中定义的默认操作的permission_classes
权限类。因此,
from rest_framework import viewsets
from rest_framework import permissions
class BaseModelViewSet(viewsets.ModelViewSet):
queryset = ''
serializer_class = ''
permission_classes = (permissions.AllowAny,)
permission_classes_by_action = {
'create': permission_classes,
'list': permission_classes,
'retrieve': permission_classes,
'update': permission_classes,
'destroy': permission_classes,
}
def get_permissions(self):
try:
return [permission() for permission in self.permission_classes_by_action[self.action]]
except KeyError:
if self.action:
action_func = getattr(self, self.action, {})
action_func_kwargs = getattr(action_func, 'kwargs', {})
permission_classes = action_func_kwargs.get('permission_classes')
else:
permission_classes = None
return [permission() for permission in (permission_classes or self.permission_classes)]
现在我们可以用这两种方式来定义permission_classes
。由于我们在超类中定义了默认的全局permission_classes_by_action
,所以我们可以在选项2中省略所有操作的定义。
class EntityViewSet(BaseModelViewSet):
"""EntityViewSet"""
queryset = Entity.objects.all()
serializer_class = EntitySerializer
permission_classes_by_action = {
'create': (permissions.IsAdminUser,),
'list': (permissions.IsAuthenticatedOrReadOnly,),
'retrieve': (permissions.AllowAny,),
'update': (permissions.AllowAny,),
'destroy': (permissions.IsAdminUser,),
'search': (permissions.IsAuthenticated,)
}
@action(detail=False, methods=['post'], permission_classes=(permissions.IsAuthenticated,))
def search(self, request, format=None):
pass