2012-07-11 183 views
2

我在短版问题:Django的login_required装饰并不重定向到前一页

我已经加入了login_required装饰,以我的观点之一。如果我在执行此视图的浏览器中输入URL,则如果用户未通过身份验证,则浏览器会正确重定向到包含我的登录表单的URL。但是,浏览器永远不会重定向回到上一页,我不知道为什么这不起作用。我尝试了数百件事情。

我在长版的问题:

我有一个单一的应用程序一个Django项目,姑且称之为my_app。我的项目的所有模板都在templates/my_app/。我有一个名为main.html的模板,其中包含多个表单,其中包括我的登录表单。通过额外的POST参数form-type,我检查哪些表单已提交。代码看起来是这样的:

def process_main_page_forms(request): 

    if request.method == 'POST': 
     if request.POST['form-type'] == u'login-form': 
      template_context = _log_user_in(request) 

     elif request.POST['form-type'] == u'registration-form': 
      template_context = _register_user(request) 

     elif request.POST['form-type'] == u'password-recovery-form': 
      template_context = _recover_password(request) 

    else: 
     template_context = { 
      'auth_form': AuthenticationForm(), 
      'registration_form': RegistrationForm(), 
      'password_recovery_form': EmailBaseForm() 
     } 

    return render(request, 'my_app/main.html', template_context) 

功能_log_user_in()看起来像这样:

def _log_user_in(request): 

    message = '' 
    username = request.POST['username'] 
    password = request.POST['password'] 
    user = authenticate(username=username, password=password) 

    if user is not None: 
     if user.is_active: 
      login(request, user) 
     else: 
      message = 'Your account has been disabled. ' \ 
         'Please contact the administrator.' 
    else: 
     message = 'Your username and password didn\'t match. Please try again.' 

    template_context = { 
     'auth_form': AuthenticationForm(), 
     'registration_form': RegistrationForm(), 
     'password_recovery_form': EmailBaseForm(), 
     'message': message, 
} 

    return template_context 

我还包括在模板中,例如必要的<input>元件登录表单是这样的:

<input type="hidden" name="form-type" value="login-form" /> 
<input type="hidden" name="next" value="{{ next }}" /> 

该视图的URL模式是:

url(r'^$', process_main_page_forms, name='main-page') 

我的第二个观点呈现了身份验证的用户更改电子邮件地址和密码两种形式。它看起来像这样:

@login_required(login_url='/') 
def change_user_credentials(request): 

    if request.method == 'POST': 

     if request.POST['form-type'] == u'change-email-form': 
      template_context = _change_email_address(request) 

     elif request.POST['form-type'] == u'change-password-form': 
      template_context = _change_password(request) 

    else: 
     template_context = {'change_email_form': ChangeEmailForm()} 

    return render(request, 'my_app/user.html', template_context) 

这第二种观点的URL模式是:

url(r'^account/$', change_user_credentials, name='user-page') 

每当我访问/account/当我没有验证,我成功地重定向到包含主页登录表单。生成的URL为http://127.0.0.1:8000/?next=/account/,其中包含必要的next参数。但是,当我登录我的帐户时,我仍然在主页上。尽管我在登录表单中提供了必要的参数next,但我从来没有将其重定向到用户页面。看来这个参数总是空的,但我不知道为什么。我的代码中也没有其他重定向调用。

你能帮我解决这个问题吗?非常感谢你提前。

+0

附注:你似乎在以一种非常奇怪的方式使用表单;而不是直接从'request.POST'获得'username'和'password',在实例化一个表单时使用'request.POST',* ie *'form = AuthenticationForm(request.POST)'然后在'form.is_valid )'。这样你得到验证(和一些消毒),你根本不需要'form-type'。它还可以解决您的代码中的当前错误,即如果密码错误,则不会记住输入的用户名。 – supervacuo 2012-07-11 19:03:22

+0

请参阅[使用表格](https://docs.djangoproject.com/en/1.4/topics/forms/)文档获取更多信息。 – supervacuo 2012-07-11 19:03:50

回答

2

可能是一个古板的答案,但没有重定向的原因是因为您似乎没有对next查询参数做任何事情。

事实上,在成功用户日志,显示在同一页面(尽管有不同的语境词典),因为如果他们试图做点别的事件:

def process_main_page_forms(request): 
    if request.method == 'POST': 
     if request.POST['form-type'] == u'login-form': 
      template_context = _log_user_in(request) 

     ... 
    ... 

    return render(request, 'my_app/main.html', template_context) 

随着Django docs explain,它是处理next参数的contrib.auth.views.login()函数,并且您没有使用该视图(尽管您使用易混淆地命名的contrib.auth.login函数)。

您应该只使用附带的视图(其中,除了处理next,还检查is_active),或添加重定向功能,以您的观点,在这种情况下,它可能是值得引进的验证码为process_main_page_forms(),除非你“再相信你一定会需要_log_user_in()别处:

from django.http import HttpResponseRedirect 
from django.conf import settings 

def process_main_page_forms(request): 
    if request.method == 'POST': 
     if request.POST['form-type'] == u'login-form': 
      username = request.POST['username'] 
      password = request.POST['password'] 

      user = authenticate(username=username, password=password) 

      if user is not None: 
       if user.is_active: 
        login(request, user) 
        if request.GET.get('next', False): 
         return HttpResponseRedirect(request.GET.get('next')) 
        else: 
         return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL) 
       else: 
        message = 'Your account has been disabled.' 
      else: 
       message = 'Your username and password didn\'t match. Please try again.' 

      # If we've reached this point then the login failed 
      template_context = { 
       'auth_form': AuthenticationForm(), 
       'registration_form': RegistrationForm(), 
       'password_recovery_form': EmailBaseForm(), 
       'message': message, 
      } 
     elif ...: 
      # Do things with other form types 
    else: 

    return render(request, 'my_app/main.html', template_context) 

example usage of contrib.auth.login有以下几点:

def my_view(request): 
    username = request.POST['username'] 
    password = request.POST['password'] 
    user = authenticate(username=username, password=password) 
    if user is not None: 
     if user.is_active: 
      login(request, user) 
      # Redirect to a success page. 
     else: 
      # Return a 'disabled account' error message 
    else: 
     # Return an 'invalid login' error message. 

你的代码几乎是那里,但你错过了“重定向到成功页面”的部分,这是next将发挥作用。

+0

非常感谢您的详细回复。事实上,我搞砸了登录视图和登录功能。我在代码中包含了你提出的'HttpResponseRedirect'调用,就像你在你的例子中一样,但它没有任何作用。你有什么想法,为什么? – pemistahl 2012-07-11 19:54:44

+0

只是一小部分。我已阅读关于登录视图,但据我了解,需要一个单独的URL模式才能正确工作。但是,我必须将上述所有三种表格都包含在上面提到的相同页面中,因为这是我的客户的要求。任何其他想法? – pemistahl 2012-07-11 20:09:30

+0

令人费解。你可以尝试一些[Simon Willison的Django调试技巧](http://simonwillison.net/2008/May/22/debugging/)来找出你为什么没有碰到'return'语句(这显然会阻止其他人你可以通过'print'语句或'raise'来了解控制流程出了什么问题,但是如果你需要更深入的学习,肯定要花几分钟时间学习'pdb' – supervacuo 2012-07-11 22:13:44

相关问题