from rest_framework import permissions
class IsOwner(permissions.BasePermission):
"""Allow only object owner to access."""
def has_object_permission(self, request, view, obj):
return obj.owner == request.user
class IsAdminOrReadOnly(permissions.BasePermission):
"""Admins can edit, others read-only."""
def has_permission(self, request, view):
if request.method in permissions.SAFE_METHODS:
return True
return request.user and request.user.is_staff
class HasAPIKey(permissions.BasePermission):
"""Require valid API key in header."""
def has_permission(self, request, view):
api_key = request.META.get('HTTP_X_API_KEY')
if not api_key:
return False
from api.models import APIKey
return APIKey.objects.filter(key=api_key, is_active=True).exists()
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
def get_permissions(self):
"""Different permissions per action."""
if self.action == 'list':
permission_classes = [permissions.AllowAny]
elif self.action == 'create':
permission_classes = [IsAuthenticated]
else:
permission_classes = [IsAuthenticated, IsOwner]
return [permission() for permission in permission_classes]
class AdminViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated, IsAdminOrReadOnly, HasAPIKey]
DRF permissions control access to API endpoints. I use built-in permissions like IsAuthenticated, IsAdminUser, or IsAuthenticatedOrReadOnly. For custom logic, I create permission classes implementing has_permission() and has_object_permission(). I combine multiple permissions with lists. Permissions run before views, short-circuiting unauthorized requests. For object-level permissions, I check ownership or roles. I use different permissions per action with get_permissions(). This provides fine-grained API access control separate from Django's auth system.