Django rest framework permission_classes of ViewSet method

前端 未结 4 2065
攒了一身酷
攒了一身酷 2020-12-08 10:43

I\'m writing a rest API with the Django REST framework, and I\'d like to protect certain endpoints with permissions. The permission classes look like they provide an elegant

4条回答
  •  悲&欢浪女
    2020-12-08 11:25

    I'm probably late to answer this, but I used a mixin, as one of the commenters pointed out. Taking the answer from @Itachi, this is my mixin implementation:

    class ViewSetActionPermissionMixin:
        def get_permissions(self):
            """Return the permission classes based on action.
    
            Look for permission classes in a dict mapping action to
            permission classes array, ie.:
    
            class MyViewSet(ViewSetActionPermissionMixin, ViewSet):
                ...
                permission_classes = [AllowAny]
                permission_action_classes = {
                    'list': [IsAuthenticated]
                    'create': [IsAdminUser]
                    'my_action': [MyCustomPermission]
                }
    
                @action(...)
                def my_action:
                    ...
    
            If there is no action in the dict mapping, then the default
            permission_classes is returned. If a custom action has its
            permission_classes defined in the action decorator, then that
            supercedes the value defined in the dict mapping.
            """
            try:
                return [
                    permission()
                    for permission in self.permission_action_classes[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
                    )
                ]
    

    And here's how to use the mixin:

    class MyViewSet(ViewSetActionPermissionMixin, ModelViewSet):
        ...
        permission_action_classes = {
            "list": [AllowAny],
            "create": [IsAdminUser],
            "custom_action": [MyCustomPermission],
        }
    
        @action(...)
        def custom_action(self, request, *args, **kwargs):
            ...
    

提交回复
热议问题