如何在ViewSet中返回403而不是404

时间:2018-04-18 09:01:50

标签: python django django-rest-framework

我正在使用API​​并拥有此ViewSet:

class ProjectViewSet(viewsets.ModelViewSet):
    # API endpoint that allows projects to be viewed or edited.
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer
    authentication_classes = used_authentication_classes
    permission_classes = (IsOwner,)

    @detail_route(methods=['get'])
    def functions(self, request, pk=None):
        project = self.get_object()
        if project is None:
            return Response({'detail': 'Missing project id'}, status=404)
        return Response([FunctionSerializer(x).data for x in Function.objects.filter(project=project)])

此API附加了权限系统。权限适用于单个资源。但是当我调用api/projects时,它应该返回用户有权访问的所有项目,它确实会返回所有项目,无论用户是否应该能够在列表中获取某个项目。

所以我覆盖了get_queryset方法,只返回用户有权访问的项目:

def get_queryset(self):
    if self.request.user.is_superuser or self.request.user.is_staff:
        return Project.objects.all()
    else:
        return Project.objects.filter(user=self.request.user.user)

这很有效,但是当我要求获取我无法访问的特定资源时,API会返回404而不是403.

我理解为什么,因为我尝试获取的资源中的PK是未定义的,因为我只返回用户有权访问的项目。我不明白的是如何解决这个问题。

有谁知道我怎么能让它返回403,或者想到我应该看的地方?

1 个答案:

答案 0 :(得分:4)

正如@Alasdair所说,404是一个慎重的选择,但如果你仍想得到403,你可以试试:

def get_queryset(self):
    user = self.request.user
    allow_all = user.is_superuser or user.is_staff
    if self.action == 'list' and not allow_all:
        return Project.objects.filter(user=user)
    return Project.objects.all()