5

I use Django Rest Framework and in my one of my viewsets class I have partial_update method (PATCH) for update my user profile. I want to create a permission for one user can update only his profile.

class ProfileViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows profiles to be viewed, added,
deleted or edited
"""
queryset = Profile.objects.all()
# serializer_class = ProfileSerializer
permission_classes = (IsAuthenticated,)
http_method_names = ['get', 'patch']

def get_queryset(self):
    user = self.request.user
    return self.queryset.filter(user=user)

def get_serializer_class(self):
    if self.action == 'list':
        return ListingMyProfileSerializer
    if self.action == 'retrieve':
        return ListingMyProfileSerializer
    if self.action == 'update':
        return ProfileSerializer
    return ProfileSerializer

def get_permissions(self):
    # Your logic should be all here
    if self.request.method == 'GET':
        self.permission_classes = (IsAuthenticated,)
    if self.request.method == 'PATCH':
        self.permission_classes = (IsAuthenticated, IsOwnerOrReject)
    return super(ProfileViewSet, self).get_permissions()

def partial_update(self, request, pk=None):
    ...
    ...

Now one user can update his profile and any other profile. I tried to create a permission class: IsOwnerOrReject but I don't know exactly what I must to do.

Braiam
  • 1
  • 11
  • 47
  • 78
FACode
  • 951
  • 1
  • 11
  • 19

2 Answers2

9

You can add a custom permission that checks whether it's his own profile. Something like this.

# permissions.py
from rest_framework import permissions
class OwnProfilePermission(permissions.BasePermission):
    """
    Object-level permission to only allow updating his own profile
    """
    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # obj here is a UserProfile instance
        return obj.user == request.user


# views.py
class ProfileViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated, OwnProfilePermission,)

UPDATE: You can remove the def get_permissions(self): part.

You can check the documentation for more info.

Rieljun Liguid
  • 1,511
  • 1
  • 10
  • 17
  • I changed but OwnProfilePermission class is not executed. I put some prints in OwnProfilePermission class and when I make a PATCH request I don't receive any print.. and I can update any profile. – FACode Aug 02 '16 at 11:24
  • @FACode did you remove the `get_permissions` method? – Rieljun Liguid Aug 02 '16 at 11:27
  • Yes. I removed but does't work. Anyway I solved the problem. Thank you @Rieljun for help :) – FACode Aug 02 '16 at 11:38
  • @FACode How you solved that? I am also getting the same problem. – Sandeep Chauhan Feb 14 '20 at 11:03
  • Got it, It is already written in [official docs](https://www.django-rest-framework.org/api-guide/permissions/#custom-permissions), **Note**: The instance-level `has_object_permission` method will only be called if the view-level `has_permission` checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call `self.check_object_permissions(request, obj)`. – Sandeep Chauhan Feb 14 '20 at 11:43
4

IsOwnerOrReject is permission class that match the user to current login user otherwise it rejects.

In your case you have to define custom permission class. Which check user is login for other profile what ever permission you want to apply. You can do it like this:

from django.contrib.auth.models import User ## Default Django User Model

class IsUpdateProfile(permissions.BasePermission):

      def has_permission(self, request, view):
           if more_condition: ## if have more condition then apply
              return True
           return request.user == User.objects.get(pk=view.kwargs['id'])
           
           
код е
  • 196
  • 2
  • 11
aman kumar
  • 3,086
  • 1
  • 17
  • 24