如何要求登录Django Generic Views?

时间:2010-01-26 15:59:28

标签: python django

我想限制对Django Generic Views处理的URL的访问。

对于我的观点,我知道login_required decorator完成了这项工作。 同时创建/删除/更新通用视图采用login_required参数,但我找不到为其他通用视图执行此操作的方法。

11 个答案:

答案 0 :(得分:95)

对于Django< 1.5,你可以通过在你的网址中包装该函数来添加一个装饰器,这允许你包装通用视图:

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装饰器包装基于类的视图的视图函数:

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

答案 1 :(得分:79)

Django 1.9或使用django-braces

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 still supports Django 1.4所以你可以使用相当旧的版本。

旧方法

我在谷歌搜索如何装饰基于类的视图时发现了这个问题,所以为此添加答案:

decorating class based views的文档部分对此进行了介绍。有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)

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

答案 2 :(得分:36)

通用视图已从功能更改为具有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'))),
)

documentation也描述了如何执行此操作。

答案 3 :(得分: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
)

答案 4 :(得分:7)

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

设置文件中的

应添加

LOGIN_URL="/login/"
你的views.py中的

from django.contrib.auth.mixins import LoginRequiredMixin

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

答案 5 :(得分:5)

实现此目的的另一种方法如下,我喜欢它与基于函数的视图完成的方式非常类似,并且不需要修改urls.py或覆盖dispatch:< / p>

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

答案 6 :(得分:3)

我想要一种可重用的方法来对从通用视图派生的许多视图要求auth。我创建了一个替换调度函数,我可以像添加其他声明一样添加到我的视图类中。

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

答案 7 :(得分:3)

在Django => 3.0中,它变得非常简单:

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

@method_decorator(login_required(login_url='/login/'), name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

以供参考:https://docs.djangoproject.com/en/3.0/topics/class-based-views/intro/#decorating-the-class

答案 8 :(得分:2)

使用以下内容:

from django.contrib.auth.decorators import login_required

@login_required
def your_view():
    # your code here

答案 9 :(得分: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);
            }
        )

答案 10 :(得分:0)

我一直在努力寻找这个问题的答案,直到我找到了这个解决方法。

在 models.py 中做: 从 django.db 导入模型

class YourLoginModel:
      fullname = models.CharField(max_length=255, default='your_name', unique=True)
      email  = models.EmailField(max_length=255, unique=True)
      username = models.CharField(max_length=255, unique=True)
      password = models.CharField(max_length=255) #using werkzeug's 
                                                  #generate_password_hash on plaintext password before committing to database model

在 forms.py 中:

from django import forms
from .models import YourLoginModel

class LoginForm(forms.ModelForm):
      class Meta:
            model = YourLoginModel
            fields = ('username', 'password')

在 views.py 登录逻辑中:

def login(request):
    #login logic here
     # init empty form
    form = LoginForm()

    if request.method == 'POST':

        try:
            # peforms a Select query in db and gets user with log in username
            user_logging_in = User.objects.get(username=request.POST['username'])

            # assign user hash to var
            hash = user_logging_in.password

            # assign form str passs word to var
            password = request.POST['password']

        # if the user does not exist
        except ObjectDoesNotExist:
            html_response = 'User does not exists'
            return HttpResponse(html_response)

        # peform password and hash check
        if check_password_hash(hash, password):
 
            #using sessions cookies to know who we're interacting with
            request.session['username'] = request.POST['username']

            #set expiry date of the session
            request.session.set_expiry(0) # 0 means when the browser is closed

            return redirect('yourapp:home')
        else:
            return HttpResponse('password was incorrect')

    html = 'Login'
    return render(request, 'login.html', {'form': form})

在应用视图中,您要执行 login_required

from django.views.generic import TemplateView

class yourTemplateView(TemplateView):
      template_name = 'your_template.html'
      def dispatch(self, request, *args, **kwrags):
           if not request.session.has_key('username'):
              #return HttpResponse('not logged in')
              return redirect('yourapp:login.html')
           else:
              return render(request, 'your_view.html')