2009-04-30 7 views
148

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

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

EDIT 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 обрабатывают это для вас, разве это не работает для вас? –

ответ

121

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

Сначала каждая страница с линией входа должна знать текущий путь, а самый простой способ - добавить препроцессор контекста запроса к параметрам 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", 
) 

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

базы.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 %} 
+40

Я лично использую это решение, но одна модификация, которую я сделал бы, это то, что он терпит неудачу, если 'request.path' равно null, поэтому я делаю это' {% firstof request.path '/'%} ', таким образом, если путь запроса недоступен по какой-либо причине, пользователь отправляется на домашнюю страницу. – jorelli

+1

Я пытаюсь реализовать ваше решение, но когда django.contrib.auth.views.login перенаправляет (после успешной аутентификации) экземпляр пользователя не находится в запросе, поэтому user.is_authenticated() всегда возвращает False. Любая помощь? – juankysmith

+3

Добавляя поверх @jorelli, вы можете использовать именованный URL и вместо этого использовать 'Login''. – hobbes3

14

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

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

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

+3

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

0

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

+0

Да, но как я могу установить «next» на страницу, с которой я пришел? –

1

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

24

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

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

У этого есть слабая точка - некоторые пользователи/браузеры передают ссылку реферирования –

+4

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

+1

И если первая подача связана с ошибкой, которую пользователь исправляет ... – Bryce

1

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

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

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

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

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

19

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

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

вместо того, чтобы просто:

?next={{ request.path }} 
+0

На самом деле это не очень хорошая идея, вы найдете строку запроса очень долго, если у вас слишком много кликов. – dspjm

-2

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

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

Неверный ответ, но name = 'next' представляется выполнимым, а не проверенным. – WeizhongTu

Смежные вопросы