使用Django Rest Framework返回当前用户


71

我目前正在使用Django开发API。

但是,我想创建一个视图,该视图返回具有以下端点的当前User:/users/current/

为此,我创建了一个列表视图,并过滤了发出请求的用户的查询集。可以,但是结果是列表,而不是单个对象。结合分页,与其他端点相比,结果看起来过于复杂且不一致。

我也尝试创建一个详细视图并过滤查询集,但是DRF抱怨我没有提供pk或slug。

你有什么主意吗?

Answers:


74

像这样的事情,您最好脱离常规视图并自己编写视图。

@api_view(['GET'])
def current_user(request):
    serializer = UserSerializer(request.user)
    return Response(serializer.data)

您也可以像这样使用基于类的视图来做同样的事情。

class CurrentUserView(APIView):
    def get(self, request):
        serializer = UserSerializer(request.user)
        return Response(serializer.data)

当然,也没有要求使用序列化程序,也可以从用户实例中提取所需的字段。

@api_view(['GET'])
def current_user(request):
    user = request.user
    return Response({
        'username': user.username,
        'email': user.email,
        ...
    })

希望能有所帮助。


27

最好的方法是使用viewsets.ModelViewSetlike的功能:

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_object(self):
        pk = self.kwargs.get('pk')

        if pk == "current":
            return self.request.user

        return super(UserViewSet, self).get_object()

viewsets.ModelViewSetmixins.CreateModelMixin+ mixins.RetrieveModelMixin+ mixins.UpdateModelMixin+ mixins.DestroyModelMixin+ mixins.ListModelMixin+的组合viewsets.GenericViewSet。如果您只需要列出全部或获得特定用户(包括当前经过身份验证的用户),则只需像这样替换它

class UserViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
    # ...

10

如果由于某种原因必须使用通用视图集,则可以执行以下操作:

class UserViewSet(viewsets.ModelViewSet):
    model = User
    serializer_class = UserSerializer

    def get_object(self):
        return self.request.user

    def list(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

retrieve当客户端使用标识符(如主键)请求单个实例时,/users/10通常会调用方法。检索自己的电话get_object。如果希望视图始终返回当前使用的视图,则可以通过调用并在其中内部进行修改get_object并强制list方法返回单个项目而不是列表self.retrieve


9

我使用了这样的ModelViewSet:

class UserViewSet(viewsets.ModelViewSet):
    model = User
    serializer_class = UserSerializer

    def dispatch(self, request, *args, **kwargs):
        if kwargs.get('pk') == 'current' and request.user:
            kwargs['pk'] = request.user.pk

        return super(UserViewSet, self).dispatch(request, *args, **kwargs)

1
易北河,我试图使用上述功能,但似乎dispatch()运行的太早了request.user仍然是匿名的,在dispatch运行之后分配了用户。
Mo J. Mughrabi

这对我来说很好用。您可能需要更改request.userrequest.user.is_authenticated()。曲子request.userAnonymousUser如果您还没有登录。
格雷格王

3
与SessionAuthentication一起使用。使用TokenAuthentication时不起作用。request.user在调度内部是匿名的。
sudokai

这不适用于令牌身份验证。执行身份验证的位置在initial()调用内部,并且在分派中完成,因此将永远不会对使用进行身份验证。
pjotr_dolphin

9

除了使用ModelViewSet的全部功能之外,还可以使用mixins。就像这里提到的那样,有RetrieveModelMixin用于检索单个对象-http: //www.django-rest-framework.org/api-guide/viewsets/#example_3

class UserViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    permission_classes = (permissions.IsAuthenticated,)
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_object(self):
        return self.request.user

如果您还需要更新模型,只需添加UpdateModelMixin。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.