Django Permissions
Controlling access to your API resources
🔒 What are Permissions?
Permissions control who can access your API endpoints. They determine whether a user can view, create, update, or delete resources, ensuring your application stays secure and organized.
# Basic permission example
from rest_framework.permissions import IsAuthenticated
class ProductView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
return Response({"message": "Only logged-in users see this"})
Built-in Permission Classes
AllowAny
Everyone can access (default)
IsAuthenticated
Only logged-in users allowed
IsAdminUser
Only admin users can access
IsAuthenticatedOrReadOnly
Read for all, write for authenticated
🔹 Using IsAuthenticated
IsAuthenticated ensures only logged-in users can access your API endpoints. This is the most common permission for protecting user-specific data and actions.
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class ProfileView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
return Response({
'username': user.username,
'email': user.email
})
# Using with ViewSets
from rest_framework import viewsets
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
permission_classes = [IsAuthenticated]
Response (Unauthorized):
{
"detail": "Authentication credentials were not provided."
}
🔹 IsAuthenticatedOrReadOnly
This permission allows anyone to read data (GET requests) but requires authentication for modifications (POST, PUT, DELETE). Perfect for public content with protected editing.
# views.py
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class BlogPostViewSet(viewsets.ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
# GET /posts/ - Anyone can view
# POST /posts/ - Must be logged in
# PUT /posts/1/ - Must be logged in
# DELETE /posts/1/ - Must be logged in
Use Cases:
- Blog posts: Public reading, authenticated writing
- Product catalogs: Browse freely, edit with login
- Forums: View threads, post with account
🔹 Custom Permissions
Create custom permission classes to implement your own access control logic. This gives you complete flexibility to define who can access what based on any criteria.
# permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission: only owners can edit
"""
def has_object_permission(self, request, view, obj):
# Read permissions for everyone
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions only for owner
return obj.owner == request.user
# views.py
class PostDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsOwnerOrReadOnly]
Permission Methods:
- has_permission: View-level check
- has_object_permission: Object-level check
- SAFE_METHODS: GET, HEAD, OPTIONS
🔹 Multiple Permissions
Combine multiple permission classes to create complex access rules. All permissions must pass for access to be granted.
# permissions.py
class IsPremiumUser(permissions.BasePermission):
def has_permission(self, request, view):
return request.user.is_premium
# views.py
class PremiumContentView(APIView):
permission_classes = [IsAuthenticated, IsPremiumUser]
def get(self, request):
return Response({"content": "Premium content here"})
# User must be both authenticated AND premium
🔹 Global Permission Settings
Set default permissions for all API views in your Django settings:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
# Now all views require authentication by default
# Override in specific views if needed
🔹 Method-Based Permissions
Apply different permissions to different HTTP methods within the same view:
# views.py
from rest_framework.decorators import action
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get_permissions(self):
if self.action in ['create', 'update', 'destroy']:
return [IsAdminUser()]
return [AllowAny()]
# GET - Anyone
# POST, PUT, DELETE - Admin only