Django: Redirect ke halaman sebelumnya setelah login

175

Saya mencoba membangun situs web sederhana dengan fungsi masuk yang sangat mirip dengan yang ada di sini di SO. Pengguna harus dapat menjelajahi situs sebagai pengguna anonim dan akan ada tautan masuk pada setiap halaman. Saat mengklik tautan login, pengguna akan dibawa ke formulir login. Setelah login berhasil, pengguna harus dibawa kembali ke halaman dari mana ia mengklik tautan login. Saya menduga bahwa saya harus meneruskan url halaman saat ini ke tampilan yang menangani formulir login tetapi saya tidak dapat membuatnya berfungsi.

EDIT: Saya sudah menemukan jawabannya. Saya menautkan ke formulir masuk dengan melewati halaman saat ini sebagai parameter GET dan kemudian menggunakan 'berikutnya' untuk mengarahkan ulang ke halaman itu. Terima kasih!

EDIT 2: Penjelasan saya sepertinya tidak jelas sehingga seperti yang diminta di sini adalah kode saya: Mari kita katakan kita berada di halaman foo.html dan kita belum login. Sekarang kita ingin memiliki tautan pada foo.html tautan itu untuk login.html. Di sana kita bisa masuk dan kemudian diarahkan kembali ke foo.html. Tautan di foo.html terlihat seperti ini:

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

Sekarang saya menulis tampilan masuk khusus yang terlihat seperti ini:

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

Dan baris penting dalam login.html:

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

Jadi ya itu cukup banyak, harapan yang membuatnya jelas.

jörg
sumber
1
Saya pikir hal-hal login Django menangani itu untuk Anda, apakah itu tidak berfungsi untuk Anda?
Dominic Rodger

Jawaban:

151

Anda tidak perlu membuat tampilan tambahan untuk ini, fungsionalitasnya sudah terpasang.

Pertama setiap halaman dengan tautan login perlu mengetahui jalur saat ini, dan cara termudah adalah menambahkan preprosessor konteks permintaan ke settings.py (4 pertama adalah default), maka objek permintaan akan tersedia di setiap permintaan:

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

Kemudian tambahkan template yang Anda inginkan tautan Login:

base.html:

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

Ini akan menambahkan argumen GET ke halaman login yang menunjuk kembali ke halaman saat ini.

Template login kemudian dapat sesederhana ini:

registrasi / login.html:

{% block content %}
<form method="post" action="">
  {{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
sverrejoh
sumber
47
Saya pribadi menggunakan solusi ini, tetapi satu modifikasi yang akan saya buat adalah gagal jika request.pathnull, jadi saya membuatnya {% firstof request.path '/' %}, dengan cara itu jika jalur permintaan tidak tersedia untuk beberapa alasan pengguna dikirim ke halaman beranda.
jorelli
1
Saya mencoba menerapkan solusi Anda, tetapi ketika django.contrib.auth.views.login pengalihan (setelah autentikasi berhasil), instance Pengguna tidak ada dalam permintaan, jadi user.is_authenticated () selalu mengembalikan False. Ada bantuan?
juankysmith
3
Menambahkan di atas @ jorelli, Anda dapat menggunakan URL bernama dan lakukan <a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>sebagai gantinya.
hobbes3
12
Anda juga harus diwaspadai jika pengguna masuk setelah hanya keluar. Dengan kata lain, nextakan menjadi seperti /accounts/logout/dan setelah pengguna login, ia akan segera keluar kembali lol, dan loop berlanjut.
hobbes3
2
Saya menemukan bahwa ini hanya berfungsi ketika saya menambahkan berikut ini ke formulir login pada Django 1.5: <input type = "hidden" name = "next" value = "{{next}}" />
Ellis Percival
28

Ini mungkin bukan "praktik terbaik", tetapi saya telah berhasil menggunakan ini sebelumnya:

return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Hibah
sumber
10
Ini memiliki titik lemah - beberapa pengguna / peramban telah melewatkan referensi yang dimatikan
Tomasz Zieliński
4
Ada juga masalah dalam kasus di mana pengguna membuka formulir, mengisi informasi dan kemudian mengirimkan. HTTP_REFERER adalah URL halaman form, dan bukan URL halaman yang berasal dari pengguna.
LaundroMat
25

Untuk mendukung url lengkap dengan param / nilai yang Anda butuhkan:

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

bukan hanya:

?next={{ request.path }}
arntg
sumber
Sebenarnya ini bukan ide yang baik, Anda akan menemukan string kueri sangat lama jika Anda memiliki terlalu banyak klik
dspjm
14

Otentikasi internal Django berfungsi seperti yang Anda inginkan.

Halaman login mereka termasuk nextstring kueri yang merupakan halaman untuk kembali setelah login.

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

S.Lott
sumber
4
Yah, dekorator login_required akan berfungsi dengan baik karena set 'di sebelah' ke halaman apa pun yang saya berasal, tetapi ketika menggunakan dekorator pengguna anonim tidak dapat melihat situs karena mereka akan langsung mengarahkan kembali ke formulir login. Saya pikir saya hanya perlu mencari cara mengatur nilai 'berikutnya' ke url halaman yang berasal dari pengguna.
jörg
1

Saya menautkan ke formulir masuk dengan melewati halaman saat ini sebagai parameter GET dan kemudian menggunakan 'berikutnya' untuk mengarahkan ulang ke halaman itu. Terima kasih!

jörg
sumber
1

Saya mengalami masalah yang sama. Solusi ini memungkinkan saya untuk tetap menggunakan tampilan login umum:

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

Dalam registration/login.html(bersarang di dalam templatesfolder) jika Anda memasukkan baris berikut, halaman tersebut akan dirender seperti halaman login admin asli Django:

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

Catatan: File hanya boleh berisi baris di atas.

Harshith JV
sumber
-1

Lihat django docs untuk views.login () , Anda memberikan nilai 'berikutnya' (sebagai bidang tersembunyi) pada formulir input untuk dialihkan ke setelah login berhasil.

YHVH
sumber
Ya, tetapi bagaimana saya benar-benar mengatur 'di sebelah' ke halaman asal saya?
jörg
-3

Anda juga bisa melakukan ini

<input type="hidden" name="text" value="{% url 'dashboard' %}" />
JREAM
sumber
Jawaban salah, tetapi nama = 'berikutnya' tampaknya layak, tidak diuji.
WeizhongTu