全局设置要求登录的所有页面?

时间:2011-12-04 17:19:47

标签: django redirect django-login

我想将未经身份验证的用户的访问权限重定向到登录页面,之后应将登录用户重定向到最初请求的页面。

根据文档,使用@user_passes_test装饰器很容易实现。但似乎我必须装饰每个视图,这是疯狂的,有太多而且容易出错。

有什么好方法可以全局启用此功能(除了一小组固定视图,例如login)?也就是说,默认情况下,只需登录即可显示所有内容,并在需要时明确处理匿名查看。

3 个答案:

答案 0 :(得分:3)

我解决这个问题的方法是使用mixin类,装饰器(或者你需要的任何代码)。虽然你必须记得调用super(Class, self).get(...)函数,所以我猜它毕竟没有那么不同。

另一方面,我发现有一组mixin执行不同的操作非常擅长于在没有太多代码的情况下获得非常简单的视图。

修改

这就是我在上一个项目中的表现:

class BaseAuthMixin(object):
    def auth_check(self, user):
        return True

    def dispatch(self, request, *args, **kwargs):
        if not self.auth_check(request.user):
            from django.http import HttpResponseRedirect
            from django.contrib.auth import logout

            is_web = False
            is_live = False

            if hasattr(self, 'get_url_name'):
                from django.core.urlresolvers import reverse
                from django.core.urlresolvers import NoReverseMatch

                try:
                    next = reverse(self.get_url_name(), kwargs=kwargs)
                except NoReverseMatch:
                    next = ''
                else:
                    next= '?next=' + next

            logout(request)

            redirect_url = settings.LOGIN_URL
            redirect_url += next

            return HttpResponseRedirect(redirect_url)
        else:
            return super(BaseAuthMixin, self).dispatch(request, *args, **kwargs)

class LoginRequiredMixin(BaseAuthMixin):
    """
    Check if the view needs the user to be logged in.
    """
    def auth_check(self, user):
        if not super(LoginRequiredMixin, self).auth_check(user):
            return False
        else:
            if hasattr(self, 'login_required'):
                if self.login_required and not user.is_authenticated():
                    return False
        return True

class MyDefaultMixin(LoginRequiredMixin):
    """
    Mixin that inherits from all common view mixins.
    """
    pass

然后上面的视图类使用(我使用Django 1.3和基于类的视图):

from django.views.generic import TemplateView

class SomeViewClass(TemplateView, MyDefaultMixin):
    # Used by 'LoginRequiredMixin' to check if a user has to be logged in
    login_required = True

    # Template for the Django TemplateView
    template_name = "some_view_template.html"

您需要一个视图来处理登录(使用settings.LOGIN_URL中的网址),其中包含一个名为next的隐藏字段的表单。此字段必须由成功登录后要转到的页面的上下文变量设置。

如果所有视图都继承自基础mixin(我上面的代码中的MyDefaultMixin),它会自动检查用户是否已登录iv视图中包含一个名为login_required的属性,并且该属性设置为True

可能有更好的方法可以做到这一点,但这就是我所做的,而且效果非常好。

答案 1 :(得分:3)

看看middleware。这些是在请求周期中的各个点运行的功能,例如,在调用每个视图之前。

因为您可能希望从中排除某些视图,所以我会查看例如csrf中间件如何与csrf_exempt装饰器一起工作。

请参阅[SOURCE]/django/views/decorators/csrf.py[SOURCE]/django/middleware/csrf.py

答案 2 :(得分:1)

from django.shortcuts import redirect
from django.conf import settings


class LoginRequiredMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.login_url = settings.LOGIN_URL
        self.open_urls = [self.login_url] + \
                         getattr(settings, 'OPEN_URLS', [])

    def __call__(self, request):
        if not request.user.is_authenticated \
        and not request.path_info in self.open_urls:
            return redirect(self.login_url+'?next='+request.path)

        return self.get_response(request)