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

157

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

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

ИЗМЕНИТЬ 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 }}">

Так что да, это очень много, надеюсь, что это ясно.

  • 1
    Я думаю, что вход в Django делает это для вас, разве это не работает для вас?
Теги:

9 ответов

129
Лучший ответ

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

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

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

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

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 %}
  • 42
    Лично я использую это решение, но я бы сделал одно изменение: он потерпит неудачу, если request.path имеет значение null, поэтому я делаю его {% firstof request.path '/' %} таким образом, если путь запроса недоступен по какой-то причине пользователь отправляется на домашнюю страницу.
  • 1
    Я пытаюсь реализовать ваше решение, но, когда django.contrib.auth.views.login перенаправляет (после успешной аутентификации), экземпляр User отсутствует в запросе, поэтому user.is_authenticated () всегда возвращает False. Любая помощь?
Показать ещё 5 комментариев
23

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

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

Чтобы поддерживать полные URL-адреса с параметрами/значениями, которые вам нужны:

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

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

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

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

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

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

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

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

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

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

1

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

urlpatterns += patterns('django.views.generic.simple',
    (r'^accounts/profile/$', 'redirect_to', {'url': 'generic_account_url'}),
)
1

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

0

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

  • 0
    Да, но как мне установить «рядом» со страницей, с которой я пришел?
-2

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

<input type="hidden" name="text" value="{% url 'dashboard' %}" />
  • 0
    Неправильный ответ, но имя = «следующий» кажется выполнимым, а не проверенным.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню