Django: Redirecionar para a página anterior após o login


175

Estou tentando criar um site simples com a funcionalidade de login muito semelhante ao aqui no SO. O usuário deve poder navegar no site como um usuário anônimo e haverá um link de login em todas as páginas. Ao clicar no link de login, o usuário será levado para o formulário de login. Após um login bem-sucedido, o usuário deve retornar à página em que clicou no link de login. Suponho que, de alguma forma, preciso passar o URL da página atual para a visualização que lida com o formulário de login, mas não consigo fazer com que funcione.

EDIT: Eu descobri isso. Eu vinculei ao formulário de login passando a página atual como um parâmetro GET e depois usei 'next' para redirecionar para essa página. Obrigado!

EDIT 2: Minha explicação não parecia clara, portanto, conforme solicitado aqui, é o meu código: Digamos que estamos em uma página foo.html e não estamos logados. Agora, gostaríamos de ter um link em foo.html que vincule para login.html. Lá, podemos fazer login e, em seguida, somos redirecionados de volta para foo.html. O link em foo.html fica assim:

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

Agora eu escrevi uma visualização de login personalizada que se parece com isso:

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

E a linha importante em login.html:

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

Então é isso mesmo, espero que fique claro.


1
Eu acho que o material de login do Django lida com isso para você, não está funcionando para você?
Dominic Rodger

Respostas:


151

Você não precisa fazer uma visualização extra para isso, a funcionalidade já está embutida.

Primeiro, cada página com um link de login precisa conhecer o caminho atual e a maneira mais fácil é adicionar o pré-promotor do contexto da solicitação a settings.py (os quatro primeiros são o padrão), e o objeto de solicitação estará disponível em cada solicitação:

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

Em seguida, adicione o modelo que você deseja no link Login:

base.html:

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

Isso adicionará um argumento GET à página de login que aponta para a página atual.

O modelo de login pode ser tão simples como este:

registration / login.html:

{% block content %}
<form method="post" action="">
  {{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}

47
Eu pessoalmente uso essa solução, mas a única modificação que eu faria é que ela falhará se request.pathfor nula; portanto, será assim {% firstof request.path '/' %}, se o caminho da solicitação não estiver disponível por algum motivo, o usuário será enviado para a página inicial.
jorelli

1
Estou tentando implementar sua solução, mas quando o django.contrib.auth.views.login redireciona (após a autenticação com êxito) a instância do usuário não está na solicitação, portanto, user.is_authenticated () sempre retorna False. Qualquer ajuda?
21712 joksmith

3
Adicionando em cima do @jorelli, você pode usar o URL nomeado e fazer isso <a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>.
hobbes3

12
Você também deve observar se um usuário faz login depois de fazer o logout. Em outras palavras, nextseria algo como /accounts/logout/e, após o login do usuário, ele será desconectado imediatamente, lol, e o loop continuará.
hobbes3

2
Eu achei que isso só funcionou quando eu adicionei o seguinte para o formulário de login no Django 1.5: <input type = "hidden" name = "next" value = "{{próximo}}" />
Ellis Percival

28

Isso pode não ser uma "prática recomendada", mas eu já usei isso com sucesso antes:

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

10
Este tem um ponto fraco - alguns usuários / navegadores têm de passar referer desligado
Tomasz Zieliński

4
Há também o problema no caso em que um usuário chega a um formulário, preenche as informações e as envia. O HTTP_REFERER é o URL da página do formulário, e não o URL da página de onde o usuário veio.
Laundromat

25

Para oferecer suporte a URLs completos com parâmetros / valores, você precisa:

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

em vez de apenas:

?next={{ request.path }}

Na verdade, esta não é uma boa idéia, você vai encontrar a string de consulta muito, muito tempo se você tem muitos cliques
dspjm

14

A autenticação embutida do Django funciona da maneira que você deseja.

Suas páginas de login incluem uma nextstring de consulta que é a página para retornar após o login.

Veja http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required


4
Bem, o decorador login_required funcionaria bem, pois define 'próximo' a qualquer página da qual eu for, mas ao usar o decorador, os usuários anônimos não podem visualizar o site porque serão redirecionados imediatamente para o formulário de login. Eu acho que só preciso descobrir como definir o valor de 'next' para o URL da página da qual o usuário vem.
jörg 30/04/09

1

Eu vinculei ao formulário de login passando a página atual como um parâmetro GET e depois usei 'next' para redirecionar para essa página. Obrigado!


1

Eu encontrei o mesmo problema. Esta solução permite que eu continue usando a visualização de login genérica:

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

1

Em registration/login.html(aninhado dentro da templatespasta), se você inserir a seguinte linha, a página será renderizada como a página de login de administrador original do Django:

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

Nota: O arquivo deve conter apenas as linhas acima.


-1

Veja os documentos do django para views.login () , você fornece um valor 'próximo' (como um campo oculto) no formulário de entrada para o qual redirecionar após um login bem-sucedido.


Sim, mas como faço para definir 'próximo' para a página de onde eu venho?
jörg 30/04/09

-3

Você também pode fazer isso

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

Resposta errada, mas name = 'next' parece viável, não testado.
WeizhongTu 5/05
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.