Django: reindirizza alla pagina precedente dopo il login


175

Sto cercando di creare un sito Web semplice con funzionalità di accesso molto simili a quello qui su SO. L'utente dovrebbe essere in grado di navigare nel sito come utente anonimo e ci sarà un link di accesso su ogni pagina. Quando si fa clic sul collegamento di accesso, l'utente verrà indirizzato al modulo di accesso. Dopo un accesso riuscito, l'utente dovrebbe essere riportato alla pagina da cui ha fatto clic sul collegamento di accesso. Suppongo di dover in qualche modo passare l'URL della pagina corrente alla vista che gestisce il modulo di accesso, ma non riesco davvero a farlo funzionare.

EDIT: l'ho capito. Ho collegato al modulo di login passando la pagina corrente come parametro GET e quindi ho usato 'next' per reindirizzare a quella pagina. Grazie!

EDIT 2: La mia spiegazione non sembra essere chiara, quindi come richiesto qui è il mio codice: Diciamo che siamo su una pagina foo.html e non siamo connessi. Ora vorremmo avere un link su foo.html che collega a login.html. Lì possiamo effettuare il login e quindi reindirizzati a foo.html. Il link su foo.html è simile al seguente:

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

Ora ho scritto una vista di accesso personalizzata che assomiglia in qualche modo a questa:

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 la riga importante in login.html:

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

Quindi sì, è praticamente tutto, spero che lo chiarisca.


1
Penso che la roba di login di Django gestisca ciò per te, non funziona per te?
Dominic Rodger,

Risposte:


151

Non è necessario creare una vista in più per questo, la funzionalità è già integrata.

Prima ogni pagina con un collegamento di accesso deve conoscere il percorso corrente e il modo più semplice è aggiungere il preprosessor del contesto della richiesta a settings.py (i primi 4 sono predefiniti), quindi l'oggetto richiesta sarà disponibile in ogni richiesta:

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

Quindi aggiungi nel modello che desideri il link di accesso:

base.html:

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

Ciò aggiungerà un argomento GET alla pagina di accesso che rimanda alla pagina corrente.

Il modello di accesso può quindi essere semplice come questo:

registrazione / login.html:

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

47
Personalmente uso questa soluzione, ma l'unica modifica che farei è che fallisce se request.pathè nulla, quindi la faccio in {% firstof request.path '/' %}questo modo se il percorso della richiesta non è disponibile per qualche motivo l'utente viene inviato alla home page.
jorelli,

1
Sto cercando di implementare la tua soluzione ma, quando django.contrib.auth.views.login reindirizza (dopo l'autenticazione correttamente) l'istanza di Utente non è nella richiesta, quindi user.is_authenticated () restituisce sempre False. Qualsiasi aiuto?
juankysmith

3
Aggiungendo sopra @jorelli, puoi usare l'URL con nome e fare <a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>invece.
hobbes3,

12
Devi anche fare attenzione se un utente accede dopo essersi disconnesso. In altre parole, nextsarebbe qualcosa di simile /accounts/logout/e dopo il login dell'utente, verrà immediatamente disconnesso di nuovo lol, e il ciclo continua.
hobbes3,

2
Ho scoperto che funzionava solo quando ho aggiunto quanto segue al modulo di login su Django 1.5: <input type = "hidden" name = "next" value = "{{next}}" />
Ellis Percival

28

Questa potrebbe non essere una "best practice", ma l'ho utilizzata con successo in precedenza:

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

10
Questo ha un punto debole - alcuni utenti / browser hanno disattivato il referer di passaggio
Tomasz Zieliński

4
C'è anche il problema nel caso in cui un utente arriva a un modulo, compila le informazioni e quindi invia. HTTP_REFERER è quindi l'URL della pagina del modulo e non l'URL della pagina da cui proviene l'utente in primo luogo.
LaundroMat,

25

Per supportare gli URL completi con parametri / valori di cui avresti bisogno:

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

invece di solo:

?next={{ request.path }}

In realtà questa non è una buona idea, troverai la stringa di query molto lunga se hai troppi clic
dspjm

14

L'autenticazione integrata di Django funziona nel modo desiderato.

Le loro pagine di accesso includono a next stringa di query che è la pagina a cui tornare dopo l'accesso.

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


4
Bene, il decoratore richiesto login_ funzionerebbe bene dato che imposta 'accanto' a qualsiasi pagina da cui provengo, ma quando si utilizza il decoratore gli utenti anonimi non possono visualizzare il sito perché verranno reindirizzati immediatamente al modulo di accesso. Penso di aver solo bisogno di capire come impostare il valore di "next" sull'URL della pagina da cui proviene l'utente.
giovedì

1

Ho collegato al modulo di login passando la pagina corrente come parametro GET e quindi ho usato 'next' per reindirizzare a quella pagina. Grazie!


1

Ho riscontrato lo stesso problema. Questa soluzione mi consente di continuare a utilizzare la vista di accesso generica:

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

1

In registration/login.html(nidificato nella templatescartella) se si inserisce la seguente riga, la pagina verrà visualizzata come la pagina di accesso dell'amministratore originale di Django:

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

Nota: il file deve contenere solo le righe sopra.


-1

Vedi django docs per views.login () , fornisci un valore "successivo" (come campo nascosto) sul modulo di input a cui reindirizzare dopo un accesso riuscito.


Sì, ma in che modo posso impostare 'prossimo' alla pagina da cui provengo?
giovedì

-3

Puoi anche farlo

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

Risposta errata, ma name = 'next' sembra fattibile, non testato.
WeizhongTu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.