Python 登录后django重定向不起作用“下一步”不发布?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16750464/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:33:57  来源:igfitidea点击:

django redirect after login not working "next" not posting?

pythondjangonext

提问by James

I have a login page which is working fine with the exception of the redirect to the referrer page. The user gets an email with a direct link within the app, they (in this example) are not logged in already and are redirected to the login page. After successful login the user is redirected to a hardcoded path. See example below.

我有一个登录页面,除了重定向到引用页面之外,它工作正常。用户收到一封带有应用程序内直接链接的电子邮件,他们(在本例中)尚未登录并被重定向到登录页面。成功登录后,用户将被重定向到硬编码路径。请参见下面的示例。

URL in email: http://localhost:8000/issueapp/1628/view/22

电子邮件中的网址: http://localhost:8000/issueapp/1628/view/22

URL of login page: http://localhost:8000/login?next=/issueapp/1628/view/22

登录页面地址: http://localhost:8000/login?next=/issueapp/1628/view/22

Login view (with hardcoded redirect):

登录视图(使用硬编码重定向):

def login_user(request):    
    state = "Please log in below..."
    username = password = ''

    if request.POST:
        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)
                state = "You're successfully logged in!"
                return HttpResponseRedirect('/issueapp/1628/')
            else:
                state = "Your account is not active, please contact the site admin."
        else:
            state = "Your username and/or password were incorrect."

    return render_to_response(
        'account_login.html',
        {
        'state':state,
        'username': username
        },
        context_instance=RequestContext(request)
    )

Login view (with "next" redirect):

登录视图(带有“下一个”重定向):

def login_user(request):    
    state = "Please log in below..."
    username = password = ''

    if request.POST:
        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)
                state = "You're successfully logged in!"
                return HttpResponseRedirect(request.GET['next'])
            else:
                state = "Your account is not active, please contact the site admin."
        else:
            state = "Your username and/or password were incorrect."

    return render_to_response(
        'account_login.html',
        {
        'state':state,
        'username': username
        },
        context_instance=RequestContext(request)
    )

The above view results in an exception "Key 'next' not found in <QueryDict: {}>"The form does not appear to be posting the "next" variable, even though its there in the url and in the form. I have searched and looked everywhere and cant figure out why its not working. Any ideas?

上面的视图导致异常"Key 'next' not found in <QueryDict: {}>"表单似乎没有发布“下一个”变量,即使它存在于 url 和表单中。我到处搜索并查看,但无法弄清楚为什么它不起作用。有任何想法吗?

Additional reference:

补充参考:

Login template:

登录模板:

{% block content %}

    {{ state }}
    <form action="/login/" method="post" >
                {% csrf_token %}
        {% if next %}
        <input type="hidden" name="next" value="{{ next }}" />
        {% endif %}
        username:
        <input type="text" name="username" value="{{ username }}" /><br />
        password:
        <input type="password" name="password" value="" /><br />

        <input type="submit" value="Log In"/>

        {% debug %}
    </form>
{% endblock %}

EDIT: The below is the code which is now working for me (thanks to the help of Paulo Bu)! **

编辑:以下是现在对我有用的代码(感谢 Paulo Bu 的帮助)!**

Login View:

登录视图:

def login_user(request):

    state = "Please log in below..."
    username = password = ''

    next = ""

    if request.GET:  
        next = request.GET['next']

    if request.POST:
        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)
                state = "You're successfully logged in!"
                if next == "":
                    return HttpResponseRedirect('/issueapp/')
                else:
                    return HttpResponseRedirect(next)
            else:
                state = "Your account is not active, please contact the site admin."
        else:
            state = "Your username and/or password were incorrect."

    return render_to_response(
        'account_login.html',
        {
        'state':state,
        'username': username,
        'next':next,
        },
        context_instance=RequestContext(request)
    )

Login Template:

登录模板:

{{ state }}

{% if next %}
<form action="/login/?next={{next}}" method="post" >
{%else%}
<form action="/login/" method="post" >
{% endif %}

            {% csrf_token %}

    username:
    <input type="text" name="username" value="{{ username }}" /><br />
    password:
    <input type="password" name="password" value="" /><br />

    <input type="submit" value="Log In"/>

    {% debug %}
</form>

采纳答案by Paulo Bu

Your code is fine, the only problem is that in the form you are passing the nextattribute as a post because the method is post. In the views you try to get the nextparameter within the getdictionary which is obvious not there.

您的代码很好,唯一的问题是在表单中您将next属性作为帖子传递,因为方法是post. 在视图中,您尝试获取字典中明显不存在的next参数get

You have to declare the html form actionlike this in order to your views work.

您必须action像这样声明 html 表单才能使您的视图工作。

{% if next %}
<form action="/login/?next={{next}}" method="post" >
{%else%}
<form action="/login/" method="post" >
{% endif %}
        {% csrf_token %}
        username:
        <input type="text" name="username" value="{{ username }}" /><br />
        password:
        <input type="password" name="password" value="" /><br />

        <input type="submit" value="Log In"/>

        {% debug %}
    </form>

There, if there is a nextvariable then you include in the urlfor retrieve it as a get parameter. If not, the form doesn't include it.

在那里,如果有一个next变量,那么您将url其作为获取参数包含在for 检索中。如果没有,则表单不包含它。

This is the best approach, but you may also fix this in your views by requesting the nextfrom the POSTdictionary like this:

这是最好的方法,但您也可以通过像这样nextPOST字典中请求来在您的视图中解决这个问题:

return HttpResponseRedirect(request.POST.get('next'))

Note that this will only work if the template account_loginhasa variable called next. You should generate it in the views and pass it to the template when you render it.

请注意,这仅在模板account_login具有名为 的变量时才有效next。您应该在视图中生成它并在渲染时将其传递给模板。

Normally, in the template you would do something like this:

通常,在模板中你会做这样的事情:

# this would be hardcoded
next = '/issueapp/1628/view/22'
# you may add some logic to generate it as you need.

and then you do:

然后你做:

return render_to_response(
    'account_login.html',
    {
    'state':state,
    'username': username,
    'next':next
    },
    context_instance=RequestContext(request)
)

Hope this helps!

希望这可以帮助!

回答by seddonym

If you want to be more generic, you could just do something like this, which passes any of the GET parameters along when the form is posted:

如果你想更通用,你可以做这样的事情,它在表单发布时传递任何 GET 参数:

<form action="/path-to-whatever/{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" method="post">

回答by Ajeeb.K.P

Instead of assigning nextin your view & passing it to template, isn't it cleaner to use ?next={{request.path}}in your template. (Remember to enable django.core.context_processors.requestin settings.py, which is usually enabled in by default in django 1.6)

不是next在您的视图中分配并将其传递给模板,而是?next={{request.path}}在您的模板中使用更干净。(记得在django.core.context_processors.requestin 中settings.py启用,在 django 1.6 中通常是默认启用的)

Here is the link tells about the same

这是链接讲述了相同的内容

https://docs.djangoproject.com/en/1.6/topics/auth/default/#the-raw-way

https://docs.djangoproject.com/en/1.6/topics/auth/default/#the-raw-way

<form action="/login/?next={{request.path}}" method="post" >

is the code required.

是需要的代码。

Note:

笔记:

You can get the current url with request.pathfrom viewalso.

您也可以使用request.pathfrom获取当前 url view

Thanks to buffer. I have just copy and pasted your comment after trying it myself in my own code.

感谢缓冲区。在我自己的代码中自己尝试后,我刚刚复制并粘贴了您的评论。

回答by Rizwan Mumtaz

Just put

就放

<form action="" method="post" >

Empty action 'what ever current complete url is'

空操作 ' what ever current complete url is'

回答by rwx

In short

简而言之

I would define in your view function next_page = request.GET['next']and then redirect to it by return HttpResponseRedirect(next_page)so you never need to change templates; just set @login_requiredand you are fine.

我会在你的视图函数中定义,next_page = request.GET['next']然后重定向到它,return HttpResponseRedirect(next_page)这样你就不需要更改模板;刚刚设置@login_required,你很好。

As example:

例如:

User A tries to access - while not logged in - https://www.domain.tld/account/. Django redirects him because @login_requiredis set to the defined LOGIN_URLin your settings.py. The method UserLoginnow tries to GETthe nextparameter and redirects to it if user A logs in successfully.

用户 A 在未登录时尝试访问https://www.domain.tld/account/。Django 重定向他,因为@login_required设置为LOGIN_URL您的 settings.py 中定义的。该方法UserLogin现在尝试GETnext参数,并成功地重定向到它,如果用户A登录。

settings.py

设置.py

LOGIN_URL = '/login/'

urls.py

网址.py

url(r'^account/', account, name='account'),
url(r'^login/$', UserLogin, name='login'),

views.py

视图.py

@login_required
def account(request):
    return HttpResponseRedirect("https://www.domain.tld/example-redirect/")

def UserLogin(request):
    next_page = request.GET['next']
    if request.user.is_authenticated():
        return HttpResponseRedirect(next_page)
    else:
        if request.method == 'POST':
            if form.is_valid():
                username = form.cleaned_data['username']
                password = form.cleaned_data['password']
                user = authenticate(email=username, password=password)
                if user is not None and user.is_active:
                    login(request, user)
                    return HttpResponseRedirect(next_page)
                else:
                    error_msg = 'There was an error!'
                    return render(request, "login", {'form': form, 'error_msg': error_msg})
            else:
                error_msg = "There was an error!"
                return render(request, "login", {'form':form, 'error_msg':error_msg})
        else:
            form = UserLoginForm()
            return render(request, "login", {'form': form})