Middleware may be your best bet. I've used this piece of code in the past, modified from a snippet found elsewhere:
import re
from django.conf import settings
from django.contrib.auth.decorators import login_required
class RequireLoginMiddleware(object):
"""
Middleware component that wraps the login_required decorator around
matching URL patterns. To use, add the class to MIDDLEWARE_CLASSES and
define LOGIN_REQUIRED_URLS and LOGIN_REQUIRED_URLS_EXCEPTIONS in your
settings.py. For example:
------
LOGIN_REQUIRED_URLS = (
r'/topsecret/(.*)$',
)
LOGIN_REQUIRED_URLS_EXCEPTIONS = (
r'/topsecret/login(.*)$',
r'/topsecret/logout(.*)$',
)
------
LOGIN_REQUIRED_URLS is where you define URL patterns; each pattern must
be a valid regex.
LOGIN_REQUIRED_URLS_EXCEPTIONS is, conversely, where you explicitly
define any exceptions (like login and logout URLs).
"""
def __init__(self):
self.required = tuple(re.compile(url) for url in settings.LOGIN_REQUIRED_URLS)
self.exceptions = tuple(re.compile(url) for url in settings.LOGIN_REQUIRED_URLS_EXCEPTIONS)
def process_view(self, request, view_func, view_args, view_kwargs):
# No need to process URLs if user already logged in
if request.user.is_authenticated():
return None
# An exception match should immediately return None
for url in self.exceptions:
if url.match(request.path):
return None
# Requests matching a restricted URL pattern are returned
# wrapped with the login_required decorator
for url in self.required:
if url.match(request.path):
return login_required(view_func)(request, *view_args, **view_kwargs)
# Explicitly return None for all non-matching requests
return None
Then in settings.py, list the base URLs you want to protect:
LOGIN_REQUIRED_URLS = (
r'/private_stuff/(.*)$',
r'/login_required/(.*)$',
)
As long as your site follows URL conventions for the pages requiring authentication, this model will work. If this isn't a one-to-one fit, you may choose to modify the middleware to suit your circumstances more closely.
What I like about this approach - besides removing the necessity of littering the codebase with @login_required
decorators - is that if the authentication scheme changes, you have one place to go to make global changes.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…