Django: Перенаправлення на попередню сторінку після входу


175

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

EDIT: Я зрозумів це. Я зв'язав форму реєстрації, передавши поточну сторінку як параметр GET, а потім застосував "наступний" для переадресації на цю сторінку. Дякую!

EDIT 2: Моє пояснення не було зрозумілим, тому тут вимагається мій код: Дозвольмо сказати, що ми перебуваємо на сторінці foo.html і ми не ввійшли в систему. Тепер ми хотіли б мати посилання на foo.html, яке посилається до входу.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
Я думаю, що вхід у Джанго вирішує, що для вас це не працює?
Домінік Роджер

Відповіді:


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

Потім додайте в шаблон, який ви хочете, посилання для входу:

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

47
Я особисто використовую це рішення, але одна з модифікацій, яку я б вніс, - це те, що вона не працює, якщо вона request.pathє нульовою, тому я роблю це {% firstof request.path '/' %}, якщо шлях запиту недоступний з певних причин, коли користувач надсилається на головну сторінку.
жореллі

1
Я намагаюся реалізувати ваше рішення, але, коли django.contrib.auth.views.login переспрямовує (після успішної автентифікації), екземпляр Користувача відсутній у запиті, тому user.is_authentication () завжди повертає 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}}" />
Ellis Percival

28

Це може бути не "найкращою практикою", але я успішно використовував це раніше:

return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))

10
Це слабке місце - деякі користувачі / браузери відключили реферера
Tomasz Zieliński

4
Проблема є і в тому випадку, коли користувач приходить до форми, заповнює інформацію та подає заявку. Тоді HTTP_REFERER - це URL-адреса сторінки форми, а не URL-адреса сторінки, з якої користувач походив.
LaundroMat

25

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

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

а не просто:

?next={{ request.path }}

Насправді це не гарна ідея, ви знайдете рядок запитів дуже дуже довго, якщо у вас буде занадто багато кліків
dspjm

14

Вбудована автентифікація Django працює так, як вам завгодно.

Їх сторінки входу містять nextрядок запиту, на яку потрібно повернутися після входу.

Подивіться на http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required


4
Що ж, декоратор login_required працював би чудово, оскільки він встановлює "поруч" з будь-якої сторінки, з якої я прийшов, але при використанні декоратора анонімні користувачі не можуть переглядати сайт, оскільки вони будуть перенаправлені на форму для входу відразу. Я думаю, що мені просто потрібно розібратися, як встановити значення "next" на URL сторінки, з якої користувач походить.
jörg

1

Я зв'язав форму реєстрації, передавши поточну сторінку як параметр GET, а потім застосував "наступний" для переадресації на цю сторінку. Дякую!


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 для views.login () , ви надаєте значення "next" (як приховане поле) у формі введення для переадресації після успішного входу.


Так, але як я насправді встановлюю "поруч" зі сторінки, з якої я прийшов?
jörg

-3

Ви також можете це зробити

<input type="hidden" name="text" value="{% url 'dashboard' %}" />

Неправильна відповідь, але name = 'next' видається можливим, не перевіреним.
WeizhongTu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.