web-dev-qa-db-fra.com

Renvoyer l'utilisateur actuel avec Django Rest Framework

Je développe actuellement une API utilisant Django.

Cependant, je voudrais créer une vue qui renvoie l'utilisateur actuel avec le point de terminaison suivant: /users/current/.

Pour ce faire, j'ai créé une vue de liste et filtré l'ensemble de requêtes sur l'utilisateur qui a fait la demande. Cela fonctionne, mais le résultat est une liste, pas un seul objet. Combiné à la pagination, le résultat semble beaucoup trop compliqué et incohérent par rapport à d'autres points finaux.

J'ai également essayé de créer une vue détaillée et de filtrer le jeu de requêtes, mais DRF se plaint de n'avoir fourni ni pk ni slug.

Avez-vous une idée?

57
Maxime

Avec quelque chose comme ça, vous feriez probablement mieux de sortir des vues génériques et d'écrire la vue vous-même.

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

Vous pouvez également faire la même chose en utilisant une vue basée sur une classe comme ça ...

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

Bien sûr, il n'y a pas non plus d'obligation d'utiliser un sérialiseur, vous pouvez tout aussi bien retirer les champs dont vous avez besoin de l'instance utilisateur.

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

J'espère que ça t'as aidé.

59
Tom Christie

La meilleure façon est d'utiliser la puissance de viewsets.ModelViewSet ainsi:

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.ModelViewSet est une combinaison de mixins.CreateModelMixin + mixins.RetrieveModelMixin + mixins.UpdateModelMixin + mixins.DestroyModelMixin + mixins.ListModelMixin + viewsets.GenericViewSet. Si vous avez juste besoin de lister tout ou d'obtenir un utilisateur particulier, y compris actuellement authentifié, il vous suffit de le remplacer comme ceci

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

Si vous devez utiliser l'ensemble de vues génériques pour une raison quelconque, vous pouvez faire quelque chose comme ça,

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 est appelée lorsque le client demande une seule instance à l'aide d'un identifiant comme une clé primaire /users/10 déclencherait normalement la méthode de récupération. Récupérer lui-même appelle get_object. Si vous souhaitez que la vue renvoie toujours le courant utilisé, vous pouvez modifier get_object et forcer la méthode list pour renvoyer un seul élément au lieu d'une liste en appelant et en renvoyant self.retrieve à l'intérieur.

9
Owais Lone

J'ai utilisé un ModelViewSet comme ceci:

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)
7
ejb

Au lieu d'utiliser toute la puissance de ModelViewSet, vous pouvez utiliser des mixins. Il y a RetrieveModelMixin utilisé pour récupérer un seul objet comme il est mentionné ici - http://www.Django-rest-framework.org/api-guide/viewsets/#example_

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

Si vous devez également mettre à jour votre modèle, ajoutez simplement UpdateModelMixin.

7
ollamh