Subjects

All subjects Django Java Python React Spring Boot JavaScript PHP
Sign Up Free
Question 7 of 10 · Django Signals & Decorators
Interview question

How do you create custom decorators for Django views to handle authentication, logging, and rate limiting? Django views के लिए custom decorators कैसे बनाते हैं - authentication, logging, rate limiting के लिए?

Answer

Custom view decorators wrap view functions to add cross-cutting concerns like authentication, request logging, rate limiting, and response modification without duplicating code.

// Custom Auth Decorator
from functools import wraps
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required

def admin_only(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        if not request.user.is_staff:
            return JsonResponse({"error": "Admin access required"}, status=403)
        return func(request, *args, **kwargs)
    return wrapper

@admin_only
def delete_user(request, user_id):
    User.objects.get(id=user_id).delete()
    return JsonResponse({"status": "deleted"})

// Custom Logging Decorator
import logging
from functools import wraps

logger = logging.getLogger(__name__)

def log_request(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        logger.info(f"User {request.user} accessing {func.__name__}")
        logger.info(f"Method: {request.method}, Path: {request.path}")
        
        try:
            response = func(request, *args, **kwargs)
            logger.info(f"Response status: {response.status_code}")
            return response
        except Exception as e:
            logger.error(f"Error in {func.__name__}: {str(e)}", exc_info=True)
            raise
    return wrapper

@log_request
def dashboard(request):
    return render(request, "dashboard.html")

// Rate Limiting Decorator
from functools import wraps
from django.core.cache import cache
from django.http import JsonResponse

def rate_limit(calls_per_minute=60):
    def decorator(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            cache_key = f"ratelimit_{request.user.id}_{func.__name__}"
            request_count = cache.get(cache_key, 0)
            
            if request_count >= calls_per_minute:
                return JsonResponse(
                    {"error": "Rate limit exceeded"},
                    status=429
                )
            
            cache.set(cache_key, request_count + 1, 60)  # 60 seconds
            return func(request, *args, **kwargs)
        return wrapper
    return decorator

@rate_limit(calls_per_minute=100)
def api_endpoint(request):
    return JsonResponse({"data": [...]})

// Combined Decorators
from django.contrib.auth.decorators import login_required

@login_required
@rate_limit(calls_per_minute=200)
@log_request
def protected_api(request):
    return JsonResponse({"data": "sensitive"})

// EXECUTION ORDER:
// 1. Check authentication
// 2. Check rate limit
// 3. Log request
// 4. Execute view

// Decorator with Arguments
def require_role(role):
    def decorator(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            if not hasattr(request.user, "profile") or request.user.profile.role != role:
                return JsonResponse({"error": "Insufficient permissions"}, status=403)
            return func(request, *args, **kwargs)
        return wrapper
    return decorator

@require_role("editor")
def publish_article(request, article_id):
    article = Article.objects.get(id=article_id)
    article.published = True
    article.save()
    return JsonResponse({"status": "published"})

// Deprecation Warning Decorator
import warnings
from functools import wraps

def deprecated(replacement=None):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            msg = f"{func.__name__} is deprecated"
            if replacement:
                msg += f". Use {replacement} instead"
            warnings.warn(msg, DeprecationWarning, stacklevel=2)
            return func(*args, **kwargs)
        return wrapper
    return decorator

@deprecated(replacement="new_api_endpoint")
def old_api_endpoint(request):
    return JsonResponse({"data": []})

Custom decorators views को wrap करके authentication, logging, rate limiting add करते हैं।

// Auth Decorator
def admin_only(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        if not request.user.is_staff:
            return JsonResponse({"error": "Admin required"}, status=403)
        return func(request, *args, **kwargs)
    return wrapper

// Rate Limiting
def rate_limit(calls_per_minute=60):
    def decorator(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            cache_key = f"ratelimit_{request.user.id}"
            count = cache.get(cache_key, 0)
            if count >= calls_per_minute:
                return JsonResponse({"error": "Rate limit"}, status=429)
            cache.set(cache_key, count + 1, 60)
            return func(request, *args, **kwargs)
        return wrapper
    return decorator

@admin_only
@rate_limit(100)
def api_view(request):
    return JsonResponse({"data": []})

Was this answer clear?