26

示例提供了一个应用程序级别视图的片段,但是如果我的“urls.py”文件中有很多不同的(和一些非应用程序)条目,包括模板,该怎么办?如何将此 login_required 装饰器应用于每个人?

(r'^foo/(?P<slug>[-\w]+)/$', 'bugs.views.bug_detail'),
(r'^$', 'django.views.generic.simple.direct_to_template', {'template':'homepage.html'}),
4

10 回答 10

28

将此放入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 中。

于 2010-07-13T14:54:29.257 回答
14

对于那些后来才知道的人,您可能会发现 django-stronghold 非常适合您的用例。您将任何要公开的网址列入白名单,其余网址需要登录。

https://github.com/mgrouchy/django-stronghold

于 2013-02-17T08:58:56.310 回答
9

这是一个稍短的中间件。

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

这意味着您必须对登录视图做一些事情,但无论如何我总是最终编写自己的身份验证后端。

于 2013-05-13T13:27:35.487 回答
8

之前的一些答案要么已经过时(旧版本的 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'
于 2019-06-13T11:06:06.140 回答
3

这是LoginRequiredMiddlewareDjango 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.LoginRequiredMiddlewareMIDDLEWARE不应该包含MIDDLEWARE_CLASSES在 settings.py 中。
  • is_authenticated是布尔而不是方法。
  • 有关更多信息,请参阅文档(尽管有些部分不是很清楚)。
于 2018-04-05T23:58:58.553 回答
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) 会在您查看之前触发,此时您可以强制进行身份验证和授权。

于 2010-07-09T16:24:23.820 回答
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'..'在必要的字符串开头。

于 2016-09-14T09:37:09.880 回答
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'

于 2018-02-14T07:00:21.897 回答
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)

注意事项:

  • 您必须将此中间件添加到 settings.py 中间件部分的最底部
  • 你应该把这个变量放在 settings.py
    • AUTH_EXEMPT_ROUTES = ('注册', '登录', '忘记密码')
于 2020-04-04T09:24:02.697 回答
-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。

于 2017-05-26T18:44:09.123 回答