Подтвердить что ты не робот

Django redirect после входа в систему не работает "next" не публикует?

У меня есть страница входа, которая работает нормально, за исключением перенаправления на страницу реферера. Пользователь получает электронное письмо с прямой ссылкой в ​​приложении, они (в этом примере) уже не вошли в систему и перенаправляются на страницу входа. После успешного входа пользователь перенаправляется на жесткий путь. См. Пример ниже.

URL в электронной почте: http://localhost:8000/issueapp/1628/view/22

URL-адрес страницы входа: http://localhost:8000/login?next=/issueapp/1628/view/22

Вход в систему (с перенаправлением с жестким кодом):

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

Вход в систему (со следующим "перенаправлением" ):

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

Вышеизложенное представление приводит к исключению "Key 'next' not found in <QueryDict: {}>" Форма, похоже, не публикует "следующую" переменную, даже если ее там в URL-адресе и в форме. Я искал и смотрел повсюду и не мог понять, почему он не работает. Любые идеи?

Дополнительная ссылка:

Шаблон для входа:

{% 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: Ниже приведен код, который теперь работает для меня (благодаря помощи Пауло Бу)! **

Вход в систему:

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

Шаблон входа:

{{ 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>
4b9b3361

Ответ 1

Ваш код в порядке, единственная проблема заключается в том, что в форме вы передаете атрибут next в качестве сообщения, потому что метод post. В представлениях вы пытаетесь получить параметр next в словаре get, который явно не существует.

Вы должны объявить html-форму action следующим образом, чтобы ваши представления работали.

{% 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>

Там, если есть переменная next, то вы включаете в url для получения ее как параметра get. Если нет, форма не включает его.

Это лучший подход, но вы также можете исправить это в своих представлениях, запросив next из словаря post следующим образом:

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

Обратите внимание, что это будет работать, только если в шаблоне account_login есть переменная с именем next. Вы должны сгенерировать его в представлениях и передать его в шаблон при его рендеринге.

Обычно в шаблоне вы делаете что-то вроде этого:

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

а затем выполните следующие действия:

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

Надеюсь, это поможет!

Ответ 2

Короче

Я бы определил в вашем представлении функцию next_page = request.GET['next'], а затем перенаправил ее на return HttpResponseRedirect(next_page), поэтому вам не нужно менять шаблоны; просто установите @login_required, и вы в порядке.

В качестве примера:

Пользователь A пытается получить доступ - пока он не вошел в систему - https://www.domain.tld/account/. Django перенаправляет его, потому что @login_required устанавливается в определенный LOGIN_URL в ваших settings.py. Метод UserLogin теперь пытается GET параметр next и перенаправляет его, если пользователь A успешно выполнил вход.

settings.py

LOGIN_URL = '/login/'

urls.py

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

views.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})

Ответ 3

Если вы хотите быть более общим, вы можете просто сделать что-то подобное, которое передает любой из параметров GET при отправке формы:

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

Ответ 4

Вместо того, чтобы назначать next в вашем представлении и передавать его в шаблон, не рекомендуется ли использовать ?next={{request.path}} в вашем шаблоне. (Не забудьте включить django.core.context_processors.request в settings.py, который по умолчанию включен в django 1.6)

Вот ссылка рассказывает о том же

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

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

- требуемый код.

Примечание:

Вы также можете получить текущий url с request.path от view.

Благодаря buffer. Я только что скопировал и вставил ваш комментарий после того, как попробовал сам в своем собственном коде.

Ответ 5

Просто поместите

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

Пустое действие 'what ever current complete url is'