该示例提供了一个应用程序级别视图的片段,但是如果我的“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 中附加projectname.middleware.LoginRequiredMiddleware
到我的 MIDDLEWARE_CLASSES 中。
对于那些后来才知道的人,您可能会发现 django-stronghold 非常适合您的用例。您将任何要公开的网址列入白名单,其余网址需要登录。
这是一个稍短的中间件。
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
这意味着您必须对登录视图做一些事情,但无论如何我总是最终编写自己的身份验证后端。
之前的一些答案要么已经过时(旧版本的 Django),要么引入了糟糕的编程实践(硬编码 URL,不使用路由)。这是我的看法,它更干燥、更可持续/可维护(改编自上面 Mehmet 的回答)。
为了突出此处的改进,这依赖于为 URL 提供路由名称(这比使用更改并具有尾随/前导斜杠的硬编码 URL/URI 更可靠)。
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'
这是LoginRequiredMiddleware
Django 1.10+ 的经典版本:
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
MIDDLEWARE
不应该包含MIDDLEWARE_CLASSES
在 settings.py 中。is_authenticated
是布尔而不是方法。使用中间件。
http://www.djangobook.com/en/2.0/chapter17/ 和 http://docs.djangoproject.com/en/1.2/topics/http/middleware/#topics-http-middleware
我假设这在 1.2 中并没有太大变化
中间件允许您创建一个具有方法的类,这些方法将在您定义的不同时间/条件下处理每个请求。
例如 process_request(request) 会在您查看之前触发,此时您可以强制进行身份验证和授权。
如果您想要这样的豁免网址(使用正则表达式),除了meder omuraliev答案之外:
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'..'在必要的字符串开头。
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',
)
像这样:'app_name.middleware.LoginRequiredMiddleware'
如果您有很多视图并且不想接触任何视图,则可以使用中间件来解决此问题。试试下面的代码:
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)
注意事项:
这是 Django 1.10+ 中新型中间件的示例:
from django.contrib.auth.decorators import login_required
from django.urls import reverse
def login_required_middleware(get_response):
"""
Require user to be logged in for all views.
"""
exceptions = {'/admin/login/'}
def middleware(request):
if request.path in exceptions:
return get_response(request)
return login_required(get_response, login_url=reverse('admin:login'))(request)
return middleware
此示例免除管理员登录表单以避免重定向循环,并将该表单用作登录 url。