python - Django的login_required装饰器不会重定向到上一页

标签 python django redirect django-templates django-views

我在简短版本中的问题:

我添加了login_required装饰者我的观点之一。如果我在执行此 View 的浏览器中输入 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 }}" />

此 View 的 URL 模式为:

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

我的第二个 View 呈现两个表单,用于更改经过身份验证的用户的电子邮件地址和密码。它看起来像这样:

@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)

第二个 View 的 URL 模式是:

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

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

你能帮我解决这个问题吗?预先非常感谢您。

最佳答案

可能是一个陈词滥调的答案,但没有发生重定向的原因是因为您似乎没有对 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() 函数,并且您没有使用该 View (尽管您使用的是令人困惑的相同 View ) -命名为contrib.auth.login函数)。

您应该只使用包含的 View (除了处理 next 之外,还检查 is_active),或者将重定向功能添加到您的 View 中,在这种情况下,可能值得将身份验证代码放入 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 发挥作用的地方。

关于python - Django的login_required装饰器不会重定向到上一页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11438451/

相关文章:

python - 是否应该只在 except block 内调用 logger.exception?为什么?

python - 带有预装依赖项的 pip 包安装

python - 正则表达式提取括号括起来的 key

python.pil : command not found

python - 在django中获取最后插入的id

python - 在 Django View 中过滤下拉查询集

ajax - AJAX 调用后的渲染问题

asp.net - 在内容页面加载之前在母版页中重定向

grails - 如何在Grails中进行201重定向?

python - CoreML 输出类型