Search code examples
djangodjango-rest-framework

DjangoRestFramework - Possible to allow certain requests only if request.user is viewing his own User object?


This is my router / URLs:

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)

I only want the user to be able to PUT, POST, PATCH and DELETE if request.user is his own User object. What I mean is, if a user goes to this URL

users/1

then DRF looks up the user whose pk is 1. If this user is not request.user, then I do not want to allow request.user to be able to POST, PUT, PATCH or DELETE. If the user is request.user, then I want to allow those requests. Is there any way for me to do this? I'm using Viewsets and I'm hoping I can continue using Viewsets to achieve this.


Solution

  • The code for accomplishing this is actually right on the docs page, at the bottom of this section. To quote it here:

    @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
    def set_password(self, request, pk=None):
        ...
    

    For that to work, you'll want to read through the Authentication and permission section of the docs, particularly the section dealing with associating data with a particular user, which suggests overriding the default perform_create view method to add an owner parameter:

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

    In response to the comment below:

    The perform_create method belongs to the GenericAPIView class, which has the following function (quoting from here:)

    This class extends REST framework's APIView class, adding commonly required behavior for standard list and detail views.

    Each of the concrete generic views provided is built by combining GenericAPIView with one or more mixin classes.

    perform_create is a function belonging to this generic class. Again quoting the same section of the docs:

    Save and deletion hooks:

    The following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.

    • perform_create(self, serializer) - Called by CreateModelMixin when saving a new object instance.
    • ...

    So, the perform_create method has no purpose other than to provide an easy way to modify what happens when creating a new object.