Django: redirigir a la página anterior después de iniciar sesión

175

Estoy tratando de construir un sitio web simple con una funcionalidad de inicio de sesión muy similar a la de SO en SO. El usuario debe poder navegar por el sitio como usuario anónimo y habrá un enlace de inicio de sesión en cada página. Al hacer clic en el enlace de inicio de sesión, el usuario será llevado al formulario de inicio de sesión. Después de un inicio de sesión exitoso, el usuario debe volver a la página desde donde hizo clic en el enlace de inicio de sesión en primer lugar. Supongo que tengo que pasar de alguna manera la URL de la página actual a la vista que maneja el formulario de inicio de sesión, pero realmente no puedo hacer que funcione.

EDITAR: lo descubrí. Me vinculé al formulario de inicio de sesión pasando la página actual como un parámetro GET y luego usé 'siguiente' para redirigir a esa página. ¡Gracias!

EDITAR 2: Mi explicación no parecía ser clara, por lo que, según lo solicitado, aquí está mi código: Digamos que estamos en una página foo.html y no hemos iniciado sesión. Ahora nos gustaría tener un enlace en foo.html que vincule para iniciar sesión.html. Allí podemos iniciar sesión y luego se nos redirige a foo.html. El enlace en foo.html se ve así:

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

Ahora escribí una vista de inicio de sesión personalizada que se parece a esto:

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

Y la línea importante en login.html:

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

Así que sí, eso es todo, espero que quede claro.

jörg
fuente
1
Creo que las cosas de inicio de sesión de Django lo manejan por usted, ¿no está funcionando para usted?
Dominic Rodger el

Respuestas:

151

No necesita hacer una vista adicional para esto, la funcionalidad ya está integrada.

Primero, cada página con un enlace de inicio de sesión debe conocer la ruta actual, y la forma más fácil es agregar el preprocesador de contexto de solicitud a settings.py (los 4 primeros son predeterminados), luego el objeto de solicitud estará disponible en cada solicitud:

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

Luego agregue en la plantilla que desea el enlace de inicio de sesión:

base.html:

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

Esto agregará un argumento GET a la página de inicio de sesión que apunta de nuevo a la página actual.

La plantilla de inicio de sesión puede ser tan simple como esta:

registro / login.html:

{% block content %}
<form method="post" action="">
  {{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
sverrejoh
fuente
47
Yo personalmente uso esta solución, pero la única modificación que haría es que falla si request.pathes nula, así que lo hago de {% firstof request.path '/' %}esa manera si la ruta de solicitud no está disponible por alguna razón, el usuario es enviado a la página de inicio.
jorelli
1
Estoy tratando de implementar su solución, pero cuando django.contrib.auth.views.login redirige (después de autenticarse con éxito) la instancia de Usuario no está en la solicitud, por lo que user.is_authenticated () siempre devuelve False. ¿Alguna ayuda?
juankysmith
3
Agregando encima de @jorelli, puede usar URL nombrada y hacer en su <a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>lugar.
hobbes3
12
También debe tener cuidado si un usuario inicia sesión después de cerrar sesión. En otras palabras, nextsería algo así /accounts/logout/y después de que el usuario inicie sesión, inmediatamente se cerrará la sesión jajaja, y el ciclo continúa.
hobbes3
2
Descubrí que esto solo funcionaba cuando agregué lo siguiente al formulario de inicio de sesión en Django 1.5: <input type = "hidden" name = "next" value = "{{next}}" />
Ellis Percival el
28

Puede que esto no sea una "mejor práctica", pero lo he usado con éxito antes:

return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Conceder
fuente
10
Esto tiene un punto débil: algunos usuarios / navegadores tienen el árbitro de pase desactivado
Tomasz Zieliński
44
También está el problema en el caso de que un usuario llegue a un formulario, complete la información y luego la envíe. HTTP_REFERER es entonces la URL de la página del formulario, y no la URL de la página de la que proviene el usuario en primer lugar.
LaundroMat
25

Para admitir URL completas con parámetros / valores que necesitaría:

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

en lugar de solo:

?next={{ request.path }}
Arntg
fuente
En realidad, esta no es una buena idea, encontrará la cadena de consulta muy larga si tiene demasiados clics
dspjm
14

La autenticación incorporada de Django funciona de la manera que desee.

Sus páginas de inicio de sesión incluyen una nextcadena de consulta que es la página a la que volverá después del inicio de sesión.

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

S.Lott
fuente
44
Bueno, el decorador login_required funcionaría bien, ya que establece 'junto' a la página de la que vengo, pero cuando se usa el decorador, los usuarios anónimos no pueden ver el sitio porque serán redirigidos al formulario de inicio de sesión de inmediato. Creo que solo necesito descubrir cómo establecer el valor de 'next' en la url de la página de donde proviene el usuario.
jörg el
1

Me vinculé al formulario de inicio de sesión pasando la página actual como un parámetro GET y luego usé 'siguiente' para redirigir a esa página. ¡Gracias!

jörg
fuente
1

Encontré el mismo problema. Esta solución me permite seguir usando la vista de inicio de sesión genérica:

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

En registration/login.html(anidado dentro de la templatescarpeta) si inserta la siguiente línea, la página se representará como la página de inicio de sesión de administrador original de Django:

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

Nota: El archivo debe contener solo las líneas anteriores.

Harshith JV
fuente
-1

Vea los documentos de django para views.login () , usted proporciona un valor 'siguiente' (como campo oculto) en el formulario de entrada para redirigir después de un inicio de sesión exitoso.

YHVH
fuente
Sí, pero ¿cómo configuro 'next' a la página de donde vengo?
jörg el
-3

También puedes hacer esto

<input type="hidden" name="text" value="{% url 'dashboard' %}" />
JREAM
fuente
Respuesta incorrecta, pero name = 'next' parece factible, no probado.
WeizhongTu