example为应用程序级别视图提供了一个片段,但如果我的“urls.py”文件中有很多不同的(和一些非应用程序)条目,包括模板,该怎么办?如何将这个login_required装饰器应用于每个装饰器?
(r'^foo/(?P<slug>[-\w]+)/$', 'bugs.views.bug_detail'),
(r'^$', 'django.views.generic.simple.direct_to_template', {'template':'homepage.html'}),
答案 0 :(得分:27)
将其放入项目根目录中的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)
然后将projectname.middleware.LoginRequiredMiddleware
附加到settings.py中的MIDDLEWARE_CLASSES。
答案 1 :(得分:13)
对于那些稍后来到这里的人,你可能会发现django-stronghold很适合你的用法。您将要公开的任何网址列入白名单,其余的则需要登录。
答案 2 :(得分:8)
这是一个稍短的中间件。
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
这意味着你必须对登录视图做一些事情,但我总是最终编写自己的auth-backend。
答案 3 :(得分:3)
这是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
是bool而不是方法。 答案 4 :(得分:2)
使用中间件。
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)会在您的视图之前触发,此时您可以强制进行身份验证和授权。
答案 5 :(得分:1)
先前的一些答案要么已经过时(Django的较旧版本),要么引入了不良的编程习惯(硬编码URL,不使用路由)。这是我认为更干燥且可持续/可维护的观点(改编自Mehmet's answer above)。
要在此处强调改进之处,这取决于为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'
答案 6 :(得分:0)
除了 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&#39; ..&#39; 在必要字符串的开头。
答案 7 :(得分:0)
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'
答案 8 :(得分:0)
如果您有很多看法而又不想碰任何人,则可以使用中间件解决此问题。请尝试以下代码:
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)
注意事项:
答案 9 :(得分:-1)
以下是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。