Implementing Django CSRF Protection via Middleware
How Django's CSRF Middleware Works
Django's CSRF protection is implemented through the CsrfViewMiddleware, which intercepts requests by calling the process_view method. Here's what happens during this process:
- Checks if the view is decorated with
@csrf_exempt - Retrieves the CSRF token from either the request body or cookies
Scenario 1: Global CSRF Enabled, Exempting Specific Views
Add the middleware to your settings.py:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
To exclude a specific function from CSRF validation, use the @csrf_exempt decorator:
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
import json
@csrf_exempt
def get_users(request):
users = ['alice', 'bob']
return HttpResponse(json.dumps(users))
Scenario 2: Global CSRF Disabled, Enabling for Specific Views
Comment out the middelware:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
To enforce CSRF protection on a specific function, use @csrf_protect:
from django.views.decorators.csrf import csrf_protect
from django.http import HttpResponse
import json
@csrf_protect
def submit_data(request):
payload = {'status': 'success'}
return HttpResponse(json.dumps(payload))
CBV Implementation with CSRF Decorators
When working with Class-Based Views, the decorator must be applied to the dispatch method using method_decorator:
Approach 1: Decorator Inside dispatch
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.http import HttpResponse
class UserProfileView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
return HttpResponse('Profile Data')
def post(self, request, *args, **kwargs):
return HttpResponse('Updated')
Approach 2: Decorator Above Class Definition
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.http import HttpResponse
@method_decorator(csrf_exempt, name='dispatch')
class ProductView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('Product List')
def post(self, request, *args, **kwargs):
return HttpResponse('Product Created')
Key Takeaways
- Django's CSRF mechanism relies on reflection in the
dispatchmethod - The request flow follows: URL routing → View → Dispatch (reflection)
- To disable CSRF on CBV views, apply decorators to the
dispatchmethod usingmethod_decorator - The
csrf_exemptdecorator works for standalone functions, while CBV requires themethod_decoratorwrapper