Introduction
Use middleware for site-wide access control that applies to all views.
Key Concepts
Middleware: Request/response processing layer.
URL-Based Access: Control access by URL pattern.
Real World Context
A B2B platform has 50+ views that should only be accessible to paying subscribers. Instead of adding @subscription_required to every view, a single middleware checks the subscription status for any URL under /app/, keeping access control centralized and impossible to forget.
Deep Dive
Role-Required Middleware
pythonfrom django.http import HttpResponseForbidden class RoleRequiredMiddleware: PROTECTED_PATHS = { '/admin/': ['admin'], '/dashboard/': ['admin', 'editor'], '/reports/': ['admin', 'analyst'], } def __init__(self, get_response): self.get_response = get_response def __call__(self, request): for path, roles in self.PROTECTED_PATHS.items(): if request.path.startswith(path): if not request.user.is_authenticated: return redirect('login') user_roles = request.user.groups.values_list('name', flat=True) if not any(role in user_roles for role in roles): return HttpResponseForbidden('Access denied') return self.get_response(request)
Subscription Middleware
pythonclass SubscriptionMiddleware: PREMIUM_PATHS = ['/premium/', '/api/premium/'] def __call__(self, request): if any(request.path.startswith(p) for p in self.PREMIUM_PATHS): if not getattr(request.user, 'has_premium', False): return redirect('upgrade') return self.get_response(request)
Common Pitfalls
- Blocking static files and login pages: If your middleware applies to all URLs, unauthenticated users cannot reach the login page or load CSS/JS. Always exclude authentication URLs and static file paths.
- Not ordering middleware correctly: Access control middleware must come after
AuthenticationMiddlewareso thatrequest.useris available. Placing it before causesAttributeError. - Heavy database queries in middleware: Middleware runs on every request. Fetching group memberships or subscription status from the database on each request adds latency. Cache the result in the session or use Django's caching framework.
Best Practices
- Keep middleware focused: Single responsibility.
- Use for cross-cutting concerns: Site-wide rules.
Summary
Middleware enforces site-wide access rules. Use for role-based URL protection. Keep logic simple and focused.