Skip to content

Django REST Permission Class Fix

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Django REST Permission Class Fix. We cover key concepts, practical examples, and best practices.

The Problem

DRF defaults allow any authenticated user to access any endpoint. When you need role-based access — admin-only delete, owner-only edit, or public read — you must configure permission classes.

Quick Fix

Wrong — no permission check on sensitive action

class AdminViewSet(viewsets.ModelViewSet):
    queryset = AdminOnlyModel.objects.all()
    serializer_class = AdminOnlySerializer
    # No permission_classes — any authenticated user can delete

Output: Any logged-in user can create, update, or delete admin resources.

Correct — global + per-view permissions

from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework import viewsets

class AdminViewSet(viewsets.ModelViewSet):
    queryset = AdminOnlyModel.objects.all()
    serializer_class = AdminOnlySerializer
    permission_classes = [IsAuthenticated, IsAdminUser]

Output: Only authenticated admin users can access the endpoint.

Custom permission class

from rest_framework.permissions import BasePermission

class IsOwner(BasePermission):
    def has_object_permission(self, request, view, obj):
        return obj.user == request.user

class OrderViewSet(viewsets.ModelViewSet):
    permission_classes = [IsAuthenticated, IsOwner]

    def get_queryset(self):
        return Order.objects.filter(user=self.request.user)

Per-action permissions

class OrderViewSet(viewsets.ModelViewSet):
    def get_permissions(self):
        if self.action == 'destroy':
            return [IsAdminUser()]
        return [IsAuthenticated()]

Prevention

  • Always set permission_classes on views that modify or expose sensitive data.
  • Use BasePermission subclass for custom object-level rules.
  • Test permissions for every action type: list, create, update, delete.

Common Mistakes with rest permission class

  1. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  2. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
  3. Using return to exit a function early instead of wrapping a pure value in the monad

These mistakes appear frequently in real-world DJANGO code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What's the difference between has_permission and has_object_permission?

has_permission runs before the action (list/create). has_object_permission runs after the object is retrieved (retrieve/update/delete).

Does permission_classes on the ViewSet override the global setting?

It combines. The view checks its own permission_classes first. If not set, global DEFAULT_PERMISSION_CLASSES applies.

What does IsAuthenticatedOrReadOnly do?

Allows GET/HEAD/OPTIONS for anyone. Requires authentication for POST/PUT/PATCH/DELETE.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro