Django: rediriger vers la page précédente après la connexion

175

J'essaie de créer un site Web simple avec une fonctionnalité de connexion très similaire à celle ici sur SO. L'utilisateur doit pouvoir naviguer sur le site en tant qu'utilisateur anonyme et il y aura un lien de connexion sur chaque page. En cliquant sur le lien de connexion, l'utilisateur sera dirigé vers le formulaire de connexion. Après une connexion réussie, l'utilisateur doit être ramené à la page à partir de laquelle il a cliqué sur le lien de connexion en premier lieu. Je suppose que je dois en quelque sorte transmettre l'URL de la page actuelle à la vue qui gère le formulaire de connexion, mais je ne peux pas vraiment le faire fonctionner.

EDIT: je l'ai compris. J'ai lié au formulaire de connexion en passant la page actuelle en tant que paramètre GET, puis j'ai utilisé «suivant» pour rediriger vers cette page. Merci!

EDIT 2: Mon explication ne semblait pas claire donc comme demandé voici mon code: Disons que nous sommes sur une page foo.html et que nous ne sommes pas connectés. Maintenant, nous aimerions avoir un lien sur foo.html qui lie à login.html. Là, nous pouvons nous connecter et nous sommes ensuite redirigés vers foo.html. Le lien sur foo.html ressemble à ceci:

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

Maintenant, j'ai écrit une vue de connexion personnalisée qui ressemble un peu à ceci:

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

Et la ligne importante dans login.html:

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

Alors oui, c'est à peu près tout, espérons que cela soit clair.

jörg
la source
1
Je pense que le truc de connexion Django gère cela pour vous, cela ne fonctionne pas pour vous?
Dominic Rodger

Réponses:

151

Vous n'avez pas besoin de créer une vue supplémentaire pour cela, la fonctionnalité est déjà intégrée.

Tout d'abord, chaque page avec un lien de connexion doit connaître le chemin actuel, et le moyen le plus simple est d'ajouter le préprocesseur de contexte de requête à settings.py (les 4 premiers sont par défaut), puis l'objet de requête sera disponible dans chaque requête:

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

Ensuite, ajoutez dans le modèle que vous voulez le lien de connexion:

base.html:

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

Cela ajoutera un argument GET à la page de connexion qui pointe vers la page actuelle.

Le modèle de connexion peut alors être aussi simple que ceci:

registration / login.html:

{% block content %}
<form method="post" action="">
  {{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
sverrejoh
la source
47
J'utilise personnellement cette solution, mais la seule modification que je ferais est qu'elle échoue si elle request.pathest nulle, donc je la fais {% firstof request.path '/' %}, de cette façon si le chemin de la demande n'est pas disponible pour une raison quelconque, l'utilisateur est envoyé à la page d'accueil.
jorelli
1
J'essaie d'implémenter votre solution mais, lorsque django.contrib.auth.views.login redirige (après s'être authentifié avec succès), l'instance de User n'est pas dans la demande, donc user.is_authenticated () retourne toujours False. De l'aide?
juankysmith
3
En ajoutant @jorelli, vous pouvez utiliser une URL nommée et le faire à la <a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>place.
hobbes3
12
Vous devez également faire attention si un utilisateur se connecte après une simple déconnexion. En d'autres termes, ce nextserait quelque chose comme /accounts/logout/et après la connexion de l'utilisateur, il sera immédiatement déconnecté lol, et la boucle continue.
hobbes3
2
J'ai trouvé que cela ne fonctionnait que lorsque j'ai ajouté ce qui suit au formulaire de connexion sur Django 1.5: <input type = "hidden" name = "next" value = "{{next}}" />
Ellis Percival
28

Ce n'est peut-être pas une "meilleure pratique", mais j'ai déjà utilisé ceci avec succès:

return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Subvention
la source
10
Cela a un point faible - certains utilisateurs / navigateurs ont désactivé le
Tomasz Zieliński
4
Il y a aussi le problème dans le cas où un utilisateur arrive à un formulaire, remplit les informations puis soumet. Le HTTP_REFERER est alors l'URL de la page de formulaire, et non l'URL de la page d'où l'utilisateur est venu en premier lieu.
LaundroMat
25

Pour prendre en charge les URL complètes avec des paramètres / valeurs dont vous avez besoin:

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

au lieu de seulement:

?next={{ request.path }}
arntg
la source
En fait ce n'est pas une bonne idée, vous trouverez la chaîne de requête très très longue si vous avez trop de clics
dspjm
14

L'authentification intégrée de Django fonctionne comme vous le souhaitez.

Leurs pages de connexion incluent une nextchaîne de requête qui est la page à laquelle revenir après la connexion.

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

S.Lott
la source
4
Eh bien, le décorateur login_required fonctionnerait très bien car il définit `` à côté '' de la page d'où je viens, mais lors de l'utilisation du décorateur, les utilisateurs anonymes ne peuvent pas voir le site car ils seront immédiatement redirigés vers le formulaire de connexion. Je pense que j'ai juste besoin de comprendre comment définir la valeur de «à côté» de l'url de la page d'où l'utilisateur provient.
jörg
1

J'ai lié au formulaire de connexion en passant la page actuelle en tant que paramètre GET, puis j'ai utilisé «suivant» pour rediriger vers cette page. Merci!

jörg
la source
1

J'ai rencontré le même problème. Cette solution me permet de continuer à utiliser la vue générique de connexion:

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

Dans registration/login.html(imbriqué dans le templatesdossier) si vous insérez la ligne suivante, la page s'affichera comme la page de connexion administrateur d'origine de Django:

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

Remarque: le fichier ne doit contenir que les lignes ci-dessus.

Harshith JV
la source
-1

Consultez la documentation de django pour views.login () , vous fournissez une valeur 'next' (sous forme de champ caché) sur le formulaire d'entrée vers laquelle rediriger après une connexion réussie.

YHVH
la source
Oui, mais comment définir «à côté» de la page d'où je viens?
jörg
-3

Vous pouvez également le faire

<input type="hidden" name="text" value="{% url 'dashboard' %}" />
JREAM
la source
Mauvaise réponse, mais name = 'next' semble faisable, non testé.
WeizhongTu