10 Powerful Django Decorators to Supercharge Your Application! 🚀
Photo by Claudio Schwarz on Unsplash

Django decorators are an incredibly powerful feature that can enhance your application’s security, performance, and maintainability by wrapping functions or class-based views with additional functionality. If you’re not utilizing them, you’re missing out!
In this article, we’ll explore 10 essential Django decorators every developer should know.
1. @login_required
– Restrict Access to Logged-in Users
If you want to ensure that only authenticated users can access a view, use @login_required
.
from django.contrib.auth.decorators import login_required
@login_required
def dashboard(request):
return render(request, "dashboard.html")
This prevents unauthenticated users from accessing sensitive pages and automatically redirects them to the login page automatically.
You can customize the URL using LOGIN_URL
and LOGIN_REDIRECT_URL
in settings.py
.
2. @permission_required
– Restrict Access Based on User Permissions
If you want to restrict access based on specific user permissions, use @permission_required
.
from django.contrib.auth.decorators import permission_required
@permission_required('myapp.can_view_dashboard')
def admin_dashboard(request):
return render(request, "admin_dashboard.html")
This ensures only users with specific permissions can access certain views.
You can use @permission_required(permission, raise_exception=True)
to raise a 403 Forbidden
error instead of redirecting users.
from django.contrib.auth.decorators import permission_required
@permission_required('myapp.can_view_dashboard', raise_exception=True)
def admin_dashboard(request):
return render(request, "admin_dashboard.html")
3. @staff_member_required
– Allow Access Only to Staff Users
If you need a quick way to restrict access to staff members? Use @staff_member_required
.
from django.contrib.admin.views.decorators import staff_member_required
@staff_member_required # only staff member can access this
def staff_dashboard(request):
return render(request, "staff_dashboard.html")
It ensures only users with is_staff=True
can access certain pages. This is ideal for admin-only views outside the Django admin panel.
4. @csrf_exempt
– Disable CSRF Protection for a View
By default, Django protects views from Cross-Site Request Forgery (CSRF) attacks. If you need to disable it (for APIs or webhooks), use @csrf_exempt
.
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def webhook(request):
return JsonResponse({"message": "Webhook received"})
This is useful for third-party API integrations (e.g., Stripe, PayPal webhooks).
Warning: Use this only when necessary, and ensure proper security measures (e.g., token authentication).
5. @require_GET
, @require_POST
, @require_http_methods
– Restrict HTTP Methods
To ensure your views only accept specific HTTP methods, use these decorators:
from django.views.decorators.http import require_GET, require_POST, require_http_methods
@require_GET
def fetch_data(request):
return JsonResponse({"data": "This is a GET request"})
@require_POST
def submit_form(request):
return JsonResponse({"message": "Form submitted!"})
@require_http_methods(["GET", "POST"])
def handle_request(request):
return JsonResponse({"message": "Only GET and POST are allowed"})
This prevents misuse of endpoints by restricting HTTP methods. It Improves security and avoids unnecessary processing for unsupported methods.
6. @cache_page
– Speed Up Your Views with Caching
If your view runs expensive database queries, use @cache_page
to cache responses for a specified time.
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # Cache for 15 minutes
def slow_view(request):
return JsonResponse({"message": "This response is cached!"})
This reduces database queries and improves response time.
7. @never_cache
– Prevent Caching for Dynamic Views
If you need to prevent caching for certain pages (e.g., dashboards, login pages), use @never_cache
.
from django.views.decorators.cache import never_cache
@never_cache
def dynamic_page(request):
return JsonResponse({"message": "Always fresh data!"})
This ensures the latest data is always displayed.
8. @transaction.atomic
– Ensure Database Consistency
When performing multiple database operations, use @transaction.atomic
to prevent partial updates if an error occurs.
from django.db import transaction
@transaction.atomic
def process_payment(request):
# Multiple DB operations
order = Order.objects.create(user=request.user, total=100)
Payment.objects.create(order=order, status="Success")
return JsonResponse({"message": "Payment processed!"})
This ensures either all database changes succeed or none do (avoiding corrupted data).
This is ideal for payment processing and bulk database updates.
9. @method_decorator
– Use Function-Based Decorators in Class-Based Views
If you’re working with class-based views (CBVs), use @method_decorator
to apply decorators to methods.
from django.utils.decorators import method_decorator
from django.views import View
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
class ProfileView(View):
@method_decorator(login_required)
def get(self, request):
return JsonResponse({"message": "Welcome to your profile!"})
This allows you to reuse function-based decorators in class-based views.
Use @method_decorator
on dispatch()
to apply it to all methods in the class.
from django.utils.decorators import method_decorator
from django.views import View
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
@method_decorator(login_required, name='dispatch') # apply dispatch
class ProfileView(View):
def get(self, request):
return JsonResponse({"message": "Welcome to your profile!"})
def post(self, request):
return JsonResponse({"message": "Profile updated successfully!"})
10. @xframe_options_deny
– Prevent Clickjacking Attacks
To protect your app from clickjacking attacks, use @xframe_options_deny
.
from django.views.decorators.clickjacking import xframe_options_deny
@xframe_options_deny
def secure_page(request):
return render(request, "secure.html")
This prevents embedding your site in an iframe, blocking clickjacking attempts.
Use @xframe_options_sameorigin
if embedding is required within the same domain.
from django.views.decorators.clickjacking import xframe_options_sameorigin
@xframe_options_sameorigin
def secure_page(request):
return render(request, "secure.html")
Wrapping Up
Django decorators help you to improve security (e.g., @csrf_exempt
, @login_required
), optimize performance (e.g., @cache_page
, @never_cache
) and maintain clean code (e.g., @method_decorator
, @transaction.atomic
)
Which decorator do you use the most? Let me know in the comments! 🚀
