Last modified: Mar 11, 2025 By Alexander Williams

Custom Django Rest Framework Permissions Guide

Django Rest Framework (DRF) provides built-in permissions for securing APIs. However, custom permissions are often needed for specific use cases. This guide will walk you through creating custom permissions in DRF.

Why Use Custom Permissions?

DRF's default permissions like IsAuthenticated or IsAdminUser are useful. But they may not fit all scenarios. Custom permissions allow you to define precise access rules for your API endpoints.

Creating a Custom Permission Class

To create a custom permission, subclass BasePermission and override the has_permission or has_object_permission methods. Below is an example:


from rest_framework.permissions import BasePermission

class IsOwnerOrReadOnly(BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """
    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request.
        if request.method in ['GET', 'HEAD', 'OPTIONS']:
            return True

        # Write permissions are only allowed to the owner.
        return obj.owner == request.user
    

In this example, the IsOwnerOrReadOnly class allows read-only access to all users. But only the owner can modify the object.

Using Custom Permissions in Views

Once your custom permission class is ready, apply it to your views. Here's how to use it in a view:


from rest_framework import generics
from .models import MyModel
from .permissions import IsOwnerOrReadOnly

class MyModelDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    permission_classes = [IsOwnerOrReadOnly]
    

This ensures only the owner can update or delete the object. Other users can only view it.

Testing Custom Permissions

Testing is crucial to ensure your permissions work as expected. Use DRF's APITestCase to write tests. Here's an example:


from django.urls import reverse
from rest_framework.test import APITestCase
from .models import MyModel

class MyModelPermissionsTest(APITestCase):
    def test_owner_can_edit(self):
        user = User.objects.create(username='owner')
        my_model = MyModel.objects.create(owner=user)
        self.client.force_authenticate(user=user)
        response = self.client.put(reverse('mymodel-detail', args=[my_model.id]), {'field': 'new_value'})
        self.assertEqual(response.status_code, 200)

    def test_non_owner_cannot_edit(self):
        user = User.objects.create(username='non_owner')
        my_model = MyModel.objects.create(owner=User.objects.create(username='owner'))
        self.client.force_authenticate(user=user)
        response = self.client.put(reverse('mymodel-detail', args=[my_model.id]), {'field': 'new_value'})
        self.assertEqual(response.status_code, 403)
    

These tests verify that only the owner can edit the object. Non-owners receive a 403 Forbidden response.

Common Use Cases for Custom Permissions

Custom permissions are useful for scenarios like:

  • Restricting access to specific user roles.
  • Allowing access based on object attributes.
  • Implementing complex business logic for access control.

For example, you might restrict access to an API endpoint based on a user's subscription plan. This can be done by checking the user's profile in the has_permission method.

Best Practices for Custom Permissions

Follow these best practices when writing custom permissions:

  • Keep permission logic simple and focused.
  • Avoid duplicating logic across multiple permission classes.
  • Test permissions thoroughly to ensure they work as expected.

For more advanced use cases, consider combining custom permissions with performance optimization techniques or API security best practices.

Conclusion

Custom permissions in Django Rest Framework are a powerful tool for securing your APIs. By following this guide, you can create and implement custom permissions tailored to your application's needs. Remember to test thoroughly and follow best practices for optimal results.

For further reading, check out our guide on DRF throttling to manage API request rates effectively.