Django: How can I apply the login_required decorator to my entire site (excluding static media)?
Dropped this into a middleware.py
file in my project root (taken from http://onecreativeblog.com/post/59051248/django-login-required-middleware)
from django.http import HttpResponseRedirect
from django.conf import settings
from re import compile
EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
"""
Middleware that requires a user to be authenticated to view any page other
than LOGIN_URL. Exemptions to this requirement can optionally be specified
in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
you can copy from your urls.py).
Requires authentication middleware and template context processors to be
loaded. You'll get an error if they aren't.
"""
def process_request(self, request):
assert hasattr(request, 'user'), "The Login Required middleware\
requires authentication middleware to be installed. Edit your\
MIDDLEWARE_CLASSES setting to insert\
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)
Then appended projectname.middleware.LoginRequiredMiddleware
to my MIDDLEWARE_CLASSES in settings.py.
For those who have come by later to this, you might find that django-stronghold fits your usecase well. You whitelist any urls you want to be public, the rest are login required.
https://github.com/mgrouchy/django-stronghold
Here's a slightly shorter middleware.
from django.contrib.auth.decorators import login_required
class LoginRequiredMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
if not getattr(view_func, 'login_required', True):
return None
return login_required(view_func)(request, *view_args, **view_kwargs)
You'll have to set "login_required" to False on each view you don't need to be logged in to see:
Function-views:
def someview(request, *args, **kwargs):
# body of view
someview.login_required = False
Class-based views:
class SomeView(View):
login_required = False
# body of view
#or
class SomeView(View):
# body of view
someview = SomeView.as_view()
someview.login_required = False
This means you'll have to do something about the login-views, but I always end up writing my own auth-backend anyway.