Search code examples
djangodjango-rest-frameworkdjango-rest-framework-permissions

What's the differences between has_object_permission and has_permission?


I am confused with the BasePermission in Django-rest-framework.

Here I defined a class: IsAuthenticatedAndOwner.

class IsAuthenticatedAndOwner(BasePermission):
    message = 'You must be the owner of this object.'
    def has_permission(self, request, view):
        print('called')
        return False
    def has_object_permission(self, request, view, obj):
        # return obj.user == request.user
        return False

Using in views.py

class StudentUpdateAPIView(RetrieveUpdateAPIView):
    serializer_class = StudentCreateUpdateSerializer
    queryset = Student.objects.all()
    lookup_field = 'pk'
    permissions_classes = [IsAuthenticatedAndOwner]

But it doesn't work at all. Everyone can pass the permission and update the data.

The called wasn't printed.


And I used to define this class: IsNotAuthenticated

class IsNotAuthenticated(BasePermission):
    message = 'You are already logged in.'
    def has_permission(self, request, view):
        return not request.user.is_authenticated()

It works well in the function

class UserCreateAPIView(CreateAPIView):
    serializer_class = UserCreateSerializer
    queryset = User.objects.all()
    permission_classes = [IsNotAuthenticated]

So, what are the differences between the examples above, and function has_object_permission & has_permission?


Solution

  • Basically, the first code denies everything because has_permission return False.

    has_permission is a check made before calling the has_object_permission. That means that you need to be allowed by has_permission before you get any chance to check the ownership test.

    What you want is:

    class IsAuthenticatedAndOwner(BasePermission):
        message = 'You must be the owner of this object.'
        def has_permission(self, request, view):
            return request.user and request.user.is_authenticated
        def has_object_permission(self, request, view, obj):
            return obj.user == request.user
    

    This will also allow authenticated users to create new items or list them.