web-dev-qa-db-ja.com

Django Rest Frameworkで現在のユーザーを返します

現在、Djangoを使用してAPIを開発しています。

ただし、次のエンドポイントを持つ現在のユーザーを返すビューを作成したいと思います:/users/current/

そのために、リストビューを作成し、要求を行ったユーザーのクエリセットをフィルター処理しました。それは機能しますが、結果は単一のオブジェクトではなくリストです。ページネーションと組み合わせた結果は、他のエンドポイントと比較して複雑すぎて一貫性がありません。

また、詳細ビューの作成とクエリセットのフィルタリングを試みましたが、DRFはpkまたはslugを提供しなかったと文句を言います。

何かアイデアはありますか?

57
Maxime

このようなものを使用すると、おそらく汎用ビューから抜け出し、自分でビューを作成するのが最善です。

@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,
        ...
    })

お役に立てば幸いです。

59
Tom Christie

最善の方法は、viewsets.ModelViewSetの力を次のように使用することです。

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は、mixins.CreateModelMixin + mixins.RetrieveModelMixin + mixins.UpdateModelMixin + mixins.DestroyModelMixin + mixins.ListModelMixin + viewsets.GenericViewSetの組み合わせです。すべてをリストするか、現在認証されている特定のユーザーを取得する必要がある場合は、このように置き換える必要があります

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

何らかの理由で汎用ビューセットを使用する必要がある場合は、次のようなことができます。

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を変更し、self.retrieveを呼び出して返すことにより、リストではなく単一のアイテムを返すようにlistメソッドを強制できます。

9
Owais Lone

次のような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)
7
ejb

ModelViewSetの全機能を使用する代わりに、ミックスインを使用できます。ここに記載されているように、単一のオブジェクトを取得するために使用されるRetrieveModelMixinがあります- 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

モデルも更新する必要がある場合は、UpdateModelMixinを追加するだけです。

7
ollamh