Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a Django REST framework /me/ call?

Suppose I have a ViewSet:

class ProfileViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows a user's profile to be viewed or edited.
    """
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly)
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

...and a HyperlinkedModelSerializer:

class ProfileSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Profile
        read_only_fields = ('user',)

I have my urls.py set up as:

router.register(r'profiles', api.ProfileViewSet, base_name='profile')

This lets me access e.g. /api/profile/1/ fine.

I want to set up a new endpoint on my API (similar to the Facebook API's /me/ call) at /api/profile/me/ to access the current user's profile - how can I do this with Django REST Framework?

like image 876
awidgery Avatar asked Dec 05 '22 03:12

awidgery


1 Answers

Using the solution by @Gerard was giving me trouble:

Expected view UserViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the .lookup_field attribute on the view correctly..

Taking a look at the source code for retrieve() it seems the user_id is not used (unused *args)

This solution is working:

from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404

from rest_framework import filters
from rest_framework import viewsets
from rest_framework import mixins
from rest_framework.decorators import list_route
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from ..serializers import UserSerializer


class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset for viewing and editing user instances.
    """
    serializer_class = UserSerializer
    User = get_user_model()
    queryset = User.objects.all()
    filter_backends = (filters.DjangoFilterBackend, filters.SearchFilter)
    filter_fields = ('username', 'email', 'usertype')
    search_fields = ('username', 'email', 'usertype')

    @list_route(permission_classes=[IsAuthenticated])
    def me(self, request, *args, **kwargs):
        User = get_user_model()
        self.object = get_object_or_404(User, pk=request.user.id)
        serializer = self.get_serializer(self.object)
        return Response(serializer.data)

Accessing /api/users/me replies with the same data as /api/users/1 (when the logged-in user is user with pk=1)

like image 58
blueFast Avatar answered Dec 26 '22 04:12

blueFast