from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.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 for any request
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions only for the owner
return obj.owner == request.user
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from .models import Article
from .permissions import IsOwnerOrReadOnly
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
I create custom permission classes to encapsulate authorization logic outside of views. This IsOwnerOrReadOnly pattern is useful for resources where anyone can read but only the owner can modify. By implementing has_object_permission, I can make granular decisions per object. I raise PermissionDenied for clarity, though returning False works too. Combining this with DRF's built-in permissions like IsAuthenticatedOrReadOnly gives fine-grained control. The key is keeping permission logic reusable and testable independently of view code.