Django: Nach dem Login zur vorherigen Seite umleiten

175

Ich versuche, eine einfache Website mit Anmeldefunktionen zu erstellen, die der hier auf SO sehr ähnlich sind. Der Benutzer sollte in der Lage sein, die Website als anonymer Benutzer zu durchsuchen, und auf jeder Seite wird ein Anmeldelink angezeigt. Wenn Sie auf den Anmeldelink klicken, wird der Benutzer zum Anmeldeformular weitergeleitet. Nach einer erfolgreichen Anmeldung sollte der Benutzer zu der Seite zurückkehren, von der aus er zuerst auf den Anmeldelink geklickt hat. Ich vermute, dass ich die URL der aktuellen Seite irgendwie an die Ansicht übergeben muss, die das Anmeldeformular verarbeitet, aber ich kann es nicht wirklich zum Laufen bringen.

EDIT: Ich habe es herausgefunden. Ich habe eine Verknüpfung zum Anmeldeformular hergestellt, indem ich die aktuelle Seite als GET-Parameter übergeben und dann 'next' verwendet habe, um zu dieser Seite umzuleiten. Vielen Dank!

EDIT 2: Meine Erklärung schien nicht klar zu sein. Wie hier angefordert, ist mein Code: Nehmen wir an, wir befinden uns auf einer Seite foo.html und sind nicht angemeldet. Jetzt möchten wir einen Link auf foo.html haben, der verlinkt zu login.html. Dort können wir uns anmelden und werden dann zurück zu foo.html umgeleitet. Der Link auf foo.html sieht folgendermaßen aus:

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

Jetzt habe ich eine benutzerdefinierte Anmeldeansicht geschrieben, die ungefähr so ​​aussieht:

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

Und die wichtige Zeile in login.html:

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

Also ja, das ist so ziemlich alles, hoffe das macht es klar.

jörg
quelle
1
Ich denke, das Django-Login-Zeug erledigt das für Sie. Funktioniert es nicht für Sie?
Dominic Rodger

Antworten:

151

Sie müssen hierfür keine zusätzliche Ansicht erstellen, die Funktionalität ist bereits integriert.

Zuerst muss jede Seite mit einem Anmeldelink den aktuellen Pfad kennen. Am einfachsten ist es, den Anforderungskontext-Präprozessor zu settings.py hinzuzufügen (die 4 ersten sind Standard). Dann ist das Anforderungsobjekt in jeder Anforderung verfügbar:

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

Fügen Sie dann in der Vorlage den gewünschten Login-Link hinzu:

base.html:

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

Dadurch wird der Anmeldeseite ein GET-Argument hinzugefügt, das auf die aktuelle Seite verweist.

Die Anmeldevorlage kann dann so einfach sein:

Registrierung / Login.html:

{% block content %}
<form method="post" action="">
  {{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
sverrejoh
quelle
47
Ich persönlich verwende diese Lösung, aber die einzige Änderung, die ich vornehmen würde, ist, dass sie fehlschlägt, wenn sie request.pathnull ist. {% firstof request.path '/' %}Wenn der Anforderungspfad aus irgendeinem Grund nicht verfügbar ist, wird der Benutzer auf die Startseite gesendet.
Jorelli
1
Ich versuche, Ihre Lösung zu implementieren, aber wenn django.contrib.auth.views.login (nach erfolgreicher Authentifizierung) umleitet, befindet sich die Instanz des Benutzers nicht in der Anforderung, sodass user.is_authenticated () immer False zurückgibt. Irgendeine Hilfe?
Juankysmith
3
Wenn Sie zusätzlich zu @jorelli hinzufügen, können Sie die benannte URL verwenden und <a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>stattdessen tun .
hobbes3
12
Sie müssen auch darauf achten, ob sich ein Benutzer nach dem Abmelden anmeldet. Mit anderen Worten, das nextwäre so etwas wie /accounts/logout/und nachdem sich der Benutzer angemeldet hat, wird er sofort wieder abgemeldet lol und die Schleife wird fortgesetzt.
hobbes3
2
Ich fand, dass dies nur funktionierte, als ich dem Anmeldeformular auf Django 1.5 Folgendes hinzufügte: <input type = "hidden" name = "next" value = "{{next}}" />
Ellis Percival
28

Dies ist möglicherweise keine "Best Practice", aber ich habe dies bereits erfolgreich angewendet:

return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Gewähren
quelle
10
Dies hat eine Schwachstelle - einige Benutzer / Browser haben Passing Referer deaktiviert
Tomasz Zieliński
4
Es gibt auch das Problem, wenn ein Benutzer zu einem Formular gelangt, die Informationen ausfüllt und dann einreicht. Der HTTP_REFERER ist dann die URL der Formularseite und nicht die URL der Seite, von der der Benutzer ursprünglich gekommen ist.
LaundroMat
25

Um vollständige URLs mit Parametern / Werten zu unterstützen, benötigen Sie:

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

statt nur:

?next={{ request.path }}
arntg
quelle
Eigentlich ist dies keine gute Idee, Sie werden die
Abfragezeichenfolge
14

Die integrierte Authentifizierung von Django funktioniert wie gewünscht.

Ihre Anmeldeseiten enthalten eine nextAbfragezeichenfolge, zu der nach der Anmeldung zurückgekehrt wird.

Schauen Sie sich http://docs.djangoproject.com/de/dev/topics/auth/#django.contrib.auth.decorators.login_required an

S.Lott
quelle
4
Nun, der login_required-Dekorator würde gut funktionieren, da er "neben" der Seite einstellt, von der ich komme, aber wenn Sie den Dekorator verwenden, können anonyme Benutzer die Site nicht anzeigen, da sie sofort zum Anmeldeformular weitergeleitet werden. Ich denke, ich muss nur herausfinden, wie der Wert von "next" neben der URL der Seite festgelegt wird, von der der Benutzer stammt.
Jörg
1

Ich habe eine Verknüpfung zum Anmeldeformular hergestellt, indem ich die aktuelle Seite als GET-Parameter übergeben und dann 'next' verwendet habe, um zu dieser Seite umzuleiten. Vielen Dank!

jörg
quelle
1

Ich bin auf das gleiche Problem gestoßen. Mit dieser Lösung kann ich weiterhin die generische Anmeldeansicht verwenden:

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

Wenn Sie in registration/login.html(im templatesOrdner verschachtelt ) die folgende Zeile einfügen, wird die Seite wie die ursprüngliche Administrator-Anmeldeseite von Django gerendert:

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

Hinweis: Die Datei sollte nur die obigen Zeilen enthalten.

Harshith JV
quelle
-1

Siehe django docs für views.login () . Sie geben einen 'nächsten' Wert (als verstecktes Feld) im Eingabeformular an, zu dem nach einer erfolgreichen Anmeldung umgeleitet werden soll.

YHVH
quelle
Ja, aber wie setze ich "neben" der Seite, von der ich komme?
Jörg
-3

Sie können dies auch tun

<input type="hidden" name="text" value="{% url 'dashboard' %}" />
JREAM
quelle
Falsche Antwort, aber name = 'next' scheint machbar, nicht getestet.
WeizhongTu