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)

Public No auth Open
🔐

IsAuthenticated

Only logged-in users allowed

Login required Secure Common
👑

IsAdminUser

Only admin users can access

Admin only Restricted Powerful
👤

IsAuthenticatedOrReadOnly

Read for all, write for authenticated

Flexible Public read Protected write

🔹 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

🧠 Test Your Knowledge

Which permission allows public reading but requires login for editing?