Django: перенаправление на предыдущую страницу после входа в систему

175

Я пытаюсь создать простой веб-сайт с функциональностью входа, очень похожей на ту, что здесь на SO. Пользователь должен иметь возможность просматривать сайт как анонимный пользователь, и на каждой странице будет ссылка для входа. При нажатии на ссылку для входа в систему пользователь попадает в форму для входа. После успешного входа в систему пользователь должен вернуться на страницу, с которой он сначала щелкнул ссылку для входа. Я предполагаю, что мне нужно каким-то образом передать URL текущей страницы представлению, которое обрабатывает форму входа, но я не могу заставить ее работать.

РЕДАКТИРОВАТЬ: Я понял это. Я связался с формой входа в систему, передав текущую страницу в качестве параметра GET, а затем использовал «следующий» для перенаправления на эту страницу. Спасибо!

РЕДАКТИРОВАТЬ 2: Мое объяснение, казалось, не было ясным, так как запрошенный здесь мой код: допустим, мы находимся на странице foo.html, и мы не вошли в систему. Теперь мы хотели бы иметь ссылку на foo.html, которая ссылается к login.html. Там мы можем войти и затем перенаправлены обратно в foo.html. Ссылка на foo.html выглядит так:

      <a href='/login/?next={{ request.path }}'>Login</a> 

Теперь я написал собственный вид входа в систему, который выглядит примерно так:

def login_view(request):
   redirect_to = request.REQUEST.get('next', '')
   if request.method=='POST':
      #create login form...
      if valid login credentials have been entered:
         return HttpResponseRedirect(redirect_to)  
   #...
   return render_to_response('login.html', locals())

И важная строка в login.html:

<form method="post" action="./?next={{ redirect_to }}">

Так что да, вот и все, надеюсь, это прояснит.

jörg
источник
1
Я думаю, что вход в Django справляется с этим, разве это не работает для вас?
Доминик Роджер

Ответы:

151

Вам не нужно делать дополнительное представление для этого, функциональность уже встроена.

Сначала каждая страница со ссылкой для входа должна знать текущий путь, и самый простой способ - добавить препроцессор контекста запроса в settings.py (по умолчанию используются 4 первых), затем объект запроса будет доступен в каждом запросе:

settings.py:

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    "django.core.context_processors.request",
)

Затем добавьте в шаблон, который вы хотите ссылку Login:

base.html:

<a href="{% url django.contrib.auth.views.login %}?next={{request.path}}">Login</a>

Это добавит аргумент GET на страницу входа, которая указывает на текущую страницу.

Шаблон входа в систему может быть таким простым:

регистрация / login.html:

{% block content %}
<form method="post" action="">
  {{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
sverrejoh
источник
47
Я лично использую это решение, но я бы сделал одно изменение: если request.pathоно пустое, произойдет сбой , поэтому я делаю его {% firstof request.path '/' %}таким образом, если путь запроса по какой-то причине недоступен, и пользователь отправляется на домашнюю страницу.
Джорелли
1
Я пытаюсь реализовать ваше решение, но когда django.contrib.auth.views.login перенаправляет (после успешной аутентификации), экземпляр User отсутствует в запросе, поэтому user.is_authenticated () всегда возвращает False. Любая помощь?
Juankysmith
3
Добавляя поверх @jorelli, вы можете использовать именованный URL и делать <a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>вместо этого.
hobbes3
12
Вы также должны следить за тем, входит ли пользователь в систему после выхода из системы. Другими словами, nextбудет что-то вроде, /accounts/logout/и после того, как пользователь войдет в систему, он сразу же выйдет из системы, lol, и цикл продолжится.
hobbes3
2
Я обнаружил, что это работает только тогда, когда я добавил следующее в форму входа в Django 1.5: <input type = "hidden" name = "next" value = "{{next}}" />
Эллис Персиваль
28

Это не может быть "лучшей практикой", но я успешно использовал это раньше:

return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Грант
источник
10
Это имеет слабое место - у некоторых пользователей / браузеров отключен проходной реферер
Томаш Зелински
4
Существует также проблема в случае, когда пользователь приходит в форму, заполняет информацию, а затем отправляет. HTTP_REFERER - это URL страницы формы, а не URL страницы, с которой пользователь пришел в первую очередь.
LaundroMat
25

Для поддержки полных URL с параметрами / значениями вам понадобится:

?next={{ request.get_full_path|urlencode }}

вместо просто:

?next={{ request.path }}
arntg
источник
На самом деле это не очень хорошая идея, вы найдете строку запроса очень очень длинной, если у вас слишком много кликов
dspjm
14

Встроенная аутентификация Django работает так, как вы хотите.

Их страницы входа включают nextстроку запроса, которая является страницей, к которой можно вернуться после входа в систему.

Посмотрите на http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required

С. Лотт
источник
4
Ну, декоратор login_required будет работать просто отлично, поскольку он устанавливает «рядом» с любой страницей, с которой я пришел, но при использовании декоратора анонимные пользователи не могут просматривать сайт, потому что они сразу же будут перенаправлены на форму входа. Я думаю, мне просто нужно выяснить, как установить значение 'next' для URL страницы, с которой приходит пользователь.
Йорг
1

Я связался с формой входа в систему, передав текущую страницу в качестве параметра GET, а затем использовал «следующий» для перенаправления на эту страницу. Спасибо!

jörg
источник
1

Я столкнулся с той же проблемой. Это решение позволяет мне продолжать использовать общий вид входа в систему:

urlpatterns += patterns('django.views.generic.simple',
    (r'^accounts/profile/$', 'redirect_to', {'url': 'generic_account_url'}),
)
мычание
источник
1

В registration/login.html(вложенный в templatesпапку), если вы вставите следующую строку, страница отобразится как оригинальная страница входа администратора Django:

{% include "admin/login.html" %}

Примечание: файл должен содержать только строки выше.

Харшит СП
источник
-1

Смотрите django docs для views.login () , вы вводите «следующее» значение (как скрытое поле) в форму ввода для перенаправления после успешного входа в систему.

YHVH
источник
Да, но как мне установить «рядом» со страницей, с которой я пришел?
Йорг
-3

Вы также можете сделать это

<input type="hidden" name="text" value="{% url 'dashboard' %}" />
JREAM
источник
Неправильный ответ, но name = 'next' кажется выполнимым, а не проверенным.
WeizhongTu