示例提供了一个应用级别视图的片段,但如果我的"urls.py"文件中有很多不同的(包括模板在内的非应用级别)条目,我该如何将login_required装饰器应用于它们中的每一个?
(r'^foo/(?P<slug>[-\w]+)/$', 'bugs.views.bug_detail'),
(r'^$', 'django.views.generic.simple.direct_to_template', {'template':'homepage.html'}),
示例提供了一个应用级别视图的片段,但如果我的"urls.py"文件中有很多不同的(包括模板在内的非应用级别)条目,我该如何将login_required装饰器应用于它们中的每一个?
(r'^foo/(?P<slug>[-\w]+)/$', 'bugs.views.bug_detail'),
(r'^$', 'django.views.generic.simple.direct_to_template', {'template':'homepage.html'}),
我把这个代码放到了我的项目根目录下的 middleware.py
文件中(源自 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)
然后在我的settings.py文件中的MIDDLEWARE_CLASSES中添加了projectname.middleware.LoginRequiredMiddleware
。
对于那些较晚了解此内容的人,您可能会发现django-stronghold非常适合您的用例。您可以将任何想要公开的URL列入白名单,而其他URL则需要登录才能访问。
middleware.py
文件,其中包含 from django.utils.deprecation import MiddlewareMixin
和 from stronghold.middleware import LoginRequiredMiddleware
。class LoginRequiredStrongholdMiddleware(MiddlewareMixin, LoginRequiredMiddleware): pass
。接下来,我在设置文件中添加了这个自定义的中间件类,而不是默认的 stronghold 类。这在 Django 1.10 中运行良好。 - MiniGunnR这是一个稍微简短的中间件。
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)
您需要在不需要登录即可查看的每个视图中将 "login_required" 设置为False:def someview(request, *args, **kwargs):
# body of view
someview.login_required = False
基于类的视图:
class SomeView(View):
login_required = False
# body of view
#or
class SomeView(View):
# body of view
someview = SomeView.as_view()
someview.login_required = False
这意味着您需要处理登录视图,但我总是编写自己的身份验证后端。from django.utils.deprecation import MiddlewareMixin
from django.urls import resolve, reverse
from django.http import HttpResponseRedirect
from my_project import settings
class LoginRequiredMiddleware(MiddlewareMixin):
"""
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 by setting a tuple of routes to ignore
"""
def process_request(self, request):
assert hasattr(request, 'user'), """
The Login Required middleware needs to be after AuthenticationMiddleware.
Also make sure to include the template context_processor:
'django.contrib.auth.context_processors.auth'."""
if not request.user.is_authenticated:
current_route_name = resolve(request.path_info).url_name
if not current_route_name in settings.AUTH_EXEMPT_ROUTES:
return HttpResponseRedirect(reverse(settings.AUTH_LOGIN_ROUTE))
settings.py
文件中,您可以定义以下内容:AUTH_EXEMPT_ROUTES = ('register', 'login', 'forgot-password')
AUTH_LOGIN_ROUTE = 'register'
--settings=mysite.path.to.different.setting_file
时,它会失败。请改用 from django.conf import settings
而不是 from my_project import settings
。 - Chris这是适用于Django 1.10+的经典LoginRequiredMiddleware
:
from django.utils.deprecation import MiddlewareMixin
class LoginRequiredMiddleware(MiddlewareMixin):
"""
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).
"""
def process_request(self, request):
assert hasattr(request, 'user'), """
The Login Required middleware needs to be after AuthenticationMiddleware.
Also make sure to include the template context_processor:
'django.contrib.auth.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)
path.to.LoginRequiredMiddleware
应该在 settings.py 的 MIDDLEWARE
中包含,而不是 MIDDLEWARE_CLASSES
。is_authenticated
是一个布尔值而不是一个方法。http://www.djangobook.com/en/2.0/chapter17/ and http://docs.djangoproject.com/en/1.2/topics/http/middleware/#topics-http-middleware
我假设在1.2版本中这个并没有太大的变化。Django 登录验证中间件
将以下代码放入 middleware.py 文件中:
from django.http import HttpResponseRedirect
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
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(MiddlewareMixin):
def process_request(self, request):
assert hasattr(request, 'user')
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)
而在 settings.py 中:
LOGIN_URL = '/app_name/login'
LOGIN_EXEMPT_URLS=(
r'/app_name/login/',
)
MIDDLEWARE_CLASSES = (
# ...
'python.path.to.LoginRequiredMiddleware',
)
除了 meder omuraliev 的答案,如果你想要排除像这样的 url(用正则表达式):
url(r'^my/url/(?P<pk>[0-9]+)/$', views.my_view, name='my_url')
将其添加到EXEMPT_URLS列表中,如下所示:
LOGIN_EXEMPT_URLS = [r'^my/url/([0-9]+)/$']
字符串开头必须有r'..'
感谢@Ehsan Ahmadi
在新版本的Django中,中间件应该像这样编写(我的Django版本=4.1.1):
middleware.py
from django.contrib.auth.decorators import login_required
from django.urls import resolve
from django.utils.deprecation import MiddlewareMixin
AUTH_EXEMPT_ROUTES = ('captcha-image', 'login', 'captcha')
class RejectAnonymousUsersMiddleware(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
current_route_name = resolve(request.path_info).url_name
if request.user.is_authenticated:
return
if current_route_name in AUTH_EXEMPT_ROUTES:
return
return login_required(view_func)(request, *view_args, **view_kwargs)
settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'myproject.middleware.RejectAnonymousUsersMiddleware',
]
import traceback
from django.contrib.auth.decorators import login_required
class RejectAnonymousUsersMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
current_route_name = resolve(request.path_info).url_name
if current_route_name in settings.AUTH_EXEMPT_ROUTES:
return
if request.user.is_authenticated:
return
return login_required(view_func)(request, *view_args, **view_kwargs)
注意事项: