ModelViewSet-Django REST框架中的不同身份验证和权限

ModelViewSet-Django REST框架中的不同身份验证和权限,django,django-rest-framework,Django,Django Rest Framework,这个问题类似于这个:,但它对我不起作用 我有以下视图集: class UserViewSet(viewsets.ModelViewSet): serializer_class = UserSerializer queryset = UserProfile.objects.none() permission_classes = [SpecialPermission] SpecialPermission如下所示: class SpecialPermission(IsAuth

这个问题类似于这个:,但它对我不起作用

我有以下视图集:

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    queryset = UserProfile.objects.none()
    permission_classes = [SpecialPermission]
SpecialPermission如下所示:

class SpecialPermission(IsAuthenticated):
    def has_permission(self, request, view):
        if request.method == 'POST':
            return True
        return super().has_permission(request, view)
REST框架设置:

"DEFAULT_AUTHENTICATION_CLASSES": ["backend.api.authentication.ExpiringTokenAuthentication"],
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
我希望每个人都能发布到UserViewSet,但其他方法都需要身份验证。然而,有了上面的代码,我在帖子上得到了一个未经授权的回复


我需要改变什么?

我想出来了:让执行身份验证变得懒惰解决了我的问题。现在我可以发布了,但身份验证仍然在需要的所有其他方法上运行

 def perform_authentication(self, request):
        """
        Perform authentication on the incoming request.

        Note that if you override this and simply 'pass', then authentication
        will instead be performed lazily, the first time either
        `request.user` or `request.auth` is accessed.
        """
        pass

虽然可以做到,但imo的这一要求并不能证明此iVology是合理的,因为与身份验证/用户相关的内容应该是干净和安全的

而是将POST方法从此视图集中提取到它自己的类中

class UserViewSet(mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    serializer_class = UserSerializer
    queryset = UserProfile.objects.none()
    permission_classes = [SpecialPermission]

如果您真的想在这个视图集中禁用身份验证,我建议您这样做

    def get_authenticators(self):
        if self.action == 'create':
            return []
        return super().get_authenticators()

这比您的解决方案更明确。

您是否尝试过
返回super(SpecialPermission,self)。拥有权限(request,view)
?它甚至不调用has\u权限,它在到达权限之前返回未经授权的权限。您为什么使用
queryset=UserProfile.objects.none()
您似乎在使用模型权限,在这里的文档中可能会有帮助。出于安全原因,我使用queryset.none()。我希望每个api点都出现在我的drf路由器中,并具有干净的url结构。我不想为创建一个额外的api端点。虽然我必须承认,从代码的角度来看,它是干净的。但我认为你可以毫无问题地将它插入同一个URL。无论如何,我添加了另一个解决方案。
    def get_authenticators(self):
        if self.action == 'create':
            return []
        return super().get_authenticators()