如何要求登录Django通用视图?


87

我想限制对Django通用视图处理的URL的访问。

对于我的观点,我知道login_required装饰器可以完成这项工作。同样,“创建/删除/更新通用视图”login_required也带有该参数,但是我找不到其他通用视图的方法。

Answers:


104

对于Django <1.5,您可以通过将函数包装在url中来添加装饰器,从而可以包装通用视图:

from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
    (r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
    )

基于函数的通用视图在Django 1.4中已弃用,在Django 1.5中已删除。但是,同样的原则适用,只需用login_required装饰器包装基于类的视图的view函数:

login_required(TemplateView.as_view(template_name='foo_index.html'))

这里如何指定login_url login_required(TemplateView.as_view(template_name ='foo_index.html'))
Saisiva A

101

Django 1.9或使用Django大括号

Django 1.9引入了LoginRequiredMixin,因此可以这样使用:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

如果您使用的是django的旧版本,则可以使用来自django-braces的几乎相同的mixin - Django版本基于django-braces版本。 django-braces 1.4.x仍然支持Django 1.4,因此您可以在相当老的版本中使用它。

较旧的方法

我在搜寻如何装饰基于类的视图时发现了这个问题,因此添加了答案:

装饰基于类的视图的文档部分中对此进行了介绍。有urls.py包装器,也可以将装饰器应用于该dispatch()方法。文档中的示例:

在URL conf中装饰

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = patterns('',
    (r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
    (r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
)

装饰课

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
    template_name = 'secret.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(ProtectedView, self).dispatch(*args, **kwargs)

有关更多详细信息,请参见上面链接的文档。


真棒!但是我只用def dispatch方法作为的子类制作了简单的类View。现在,我可以简单地进行如下操作:class ProtectedTemplateView(TemplateView, ProtectedView): pass
WBAR 2013年

如果我不设置login_url而是在settings.py上进行设置,则默认情况下会重定向到该名称吗?
Marat Mkitaryan '19

38

通用视图已从功能更改为Django 1.3版的对象。因此,Will McCutchen和Will Hardy的答案需要与版本1.3稍作更改:

from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView

urlpatterns = patterns('',
    (r'^foo/$', login_required(TemplateView.as_view(template_name='foo_index.html'))),
)

此外,文档还介绍了如何执行此操作。


2
请读者,考虑到这个答案导致时间流逝和软件发展。第一个解决方案对我不起作用。
n3storm

12

如果您不想围绕所讨论的通用视图编写自己的精简包装(如Aamir所建议),则还可以在urls.py文件中执行以下操作:

from django.conf.urls.defaults import *

# Directly import whatever generic views you're using and the login_required
# decorator
from django.views.generic.simple import direct_to_template
from django.contrib.auth.decorators import login_required

# In your urlpatterns, wrap the generic view with the decorator
urlpatterns = patterns('',
    (r'', login_required(direct_to_template), {'template': 'index.html'}),
    # etc
)

8

对于django 1.11,可以将LoginRequiredMixin用于基于类的视图

在设置文件中,您应该添加

LOGIN_URL="/login/"

在您的views.py中

from django.contrib.auth.mixins import LoginRequiredMixin

class RestaurantLocationCreateView(LoginRequiredMixin,CreateView):
    ....

8

下面是实现此目的的另一种方法,我喜欢它与基于函数的视图非常相似,并且不需要修改urls.py或覆盖dispatch

@method_decorator(login_required, name='dispatch')
class YourGenericViewSubclass(TemplateView):
    #
    # View methods
    #

3

我想要一种可重用的方法,要求对从通用视图派生的许多视图进行身份验证。我创建了一个替换调度函数,可以使用与其他声明相同的方式将其添加到视图类中。

class Index(generic.ListView):
    model = models.HomePage
    dispatch = auth.dispatch

auth.dispatch是我们要做的工作:

def dispatch(self, request, *args, **kw):
    """Mix-in for generic views"""
    if userSession(request):
        return  super(self.__class__, self).dispatch(request, *args, **kw)

    # auth failed, return login screen
    response = user(request)
    response.set_cookie('afterauth', value=request.path_info)
    return response


1

使用以下内容:

from django.contrib.auth.decorators import login_required

@login_required
def your_view():
    # your code here

5
根据问题的日期,我认为OP正在为django基于类的通用视图而不是基于函数的视图寻求解决方案。
多尔夫(Dolph)

0

以下可以解决此问题。

// in views.py:
class LoginAuthenAJAX(View):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            jsonr = json.dumps({'authenticated': True})
        else:
            jsonr = json.dumps({'authenticated': False})
        return HttpResponse(jsonr, content_type='application/json')

// in urls.py
    path('login_auth', views.LoginAuthenAJAX.as_view(), name="user_verify"),

//in xxx.html
<script src = “{% static “xxx/script.js” %}” 
var login_auth_link = “{%  url ‘user_verify’ %}”
</script>

// in script.js
        $.get(login_auth_link, {
            'csrfmiddlewaretoken' : csrf_token,
            },
            function(ret){
                if (ret.authenticated == false) {
                    window.location.pathname="/accounts/login/"
                }
                $("#message").html(ret.result);
            }
        )
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.