Django: เปลี่ยนเส้นทางไปยังหน้าก่อนหน้าหลังจากเข้าสู่ระบบ


175

ฉันกำลังพยายามสร้างเว็บไซต์อย่างง่ายที่มีฟังก์ชั่นเข้าสู่ระบบคล้ายกับที่นี่ใน SO ผู้ใช้ควรสามารถเรียกดูไซต์ในฐานะผู้ใช้ที่ไม่ระบุชื่อและจะมีลิงค์ล็อกอินในทุกหน้า เมื่อคลิกที่ลิงค์เข้าสู่ระบบผู้ใช้จะถูกนำไปที่แบบฟอร์มการเข้าสู่ระบบ หลังจากเข้าสู่ระบบที่ประสบความสำเร็จผู้ใช้ควรจะกลับไปที่หน้าจากที่เขาคลิกลิงค์เข้าสู่ระบบในสถานที่แรก ฉันคาดเดาว่าฉันจะต้องผ่าน URL ของหน้าปัจจุบันไปยังมุมมองที่จัดการกับแบบฟอร์มการเข้าสู่ระบบ แต่ฉันไม่สามารถทำให้มันใช้งานได้

แก้ไข: ฉันคิดออก ฉันเชื่อมโยงไปยังแบบฟอร์มการเข้าสู่ระบบโดยส่งหน้าปัจจุบันเป็นพารามิเตอร์ GET แล้วใช้ 'ถัดไป' เพื่อเปลี่ยนเส้นทางไปยังหน้านั้น ขอบคุณ!

แก้ไข 2: คำอธิบายของฉันดูเหมือนจะไม่ชัดเจนดังนั้นตามที่ขอนี่คือรหัสของฉัน: ให้บอกว่าเราอยู่ในหน้า foo.html และเราไม่ได้เข้าสู่ระบบตอนนี้เราอยากจะมีลิงค์ใน foo.html ที่ลิงค์ เพื่อ login.html ที่นั่นเราสามารถเข้าสู่ระบบแล้วเปลี่ยนเส้นทางกลับไปที่ foo.html ลิงก์ใน foo.html มีลักษณะดังนี้:

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

ตอนนี้ฉันได้เขียนมุมมองเข้าสู่ระบบแบบกำหนดเองที่มีลักษณะเช่นนี้:

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

และบรรทัดสำคัญใน login.html:

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

ดังนั้นใช่ว่ามันค่อนข้างมากหวังว่าจะทำให้ชัดเจน


1
ฉันคิดว่าข้อมูลการเข้าสู่ระบบ Django จัดการกับคุณไม่ได้ผลกับคุณหรือไม่?
Dominic Rodger

คำตอบ:


151

คุณไม่จำเป็นต้องทำมุมมองเพิ่มเติมสำหรับสิ่งนี้ฟังก์ชั่นที่มีอยู่แล้วใน

ก่อนอื่นแต่ละเพจที่มีลิงค์เข้าสู่ระบบจำเป็นต้องรู้เส้นทางปัจจุบันและวิธีที่ง่ายที่สุดคือการเพิ่มบริบทการเตรียมการล่วงหน้าให้กับ settings.py (4 อันดับแรกเป็นค่าเริ่มต้น) จากนั้นวัตถุคำขอจะมีอยู่ในแต่ละคำขอ:

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

จากนั้นเพิ่มเทมเพลตที่คุณต้องการในลิงค์ล็อกอิน:

base.html:

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

สิ่งนี้จะเพิ่มอาร์กิวเมนต์ GET ให้กับหน้าเข้าสู่ระบบที่ชี้กลับไปที่หน้าปัจจุบัน

เทมเพลตการเข้าสู่ระบบนั้นง่ายมากเช่นนี้:

ลงทะเบียน / login.html:

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

47
ฉันใช้โซลูชันนี้เป็นการส่วนตัว แต่การปรับเปลี่ยนอย่างใดอย่างหนึ่งที่ฉันทำได้คือมันล้มเหลวหากrequest.pathเป็นโมฆะดังนั้นฉันจึงทำ{% firstof request.path '/' %}เช่นนั้นหากเส้นทางคำขอไม่พร้อมใช้งานด้วยเหตุผลบางประการที่ผู้ใช้ได้รับการส่งไปที่หน้าแรก
jorelli

1
ฉันกำลังพยายามใช้โซลูชันของคุณ แต่เมื่อ django.contrib.auth.views.login เปลี่ยนเส้นทาง (หลังจากตรวจสอบสิทธิ์สำเร็จ) อินสแตนซ์ของผู้ใช้ไม่ได้อยู่ในคำขอดังนั้น user.is_authenticated () จะส่งกลับค่า False เสมอ ความช่วยเหลือใด ๆ
juankysmith

3
การเพิ่มที่ด้านบนของ @jorelli คุณสามารถใช้ URL ที่มีชื่อและทำ<a href="{% url auth_login %}?next={% firstof request.path '/' %}">Login</a>แทน
hobbes3

12
คุณต้องระวังหากผู้ใช้เข้าสู่ระบบหลังจากเพิ่งออกจากระบบ ในคำอื่น ๆnextจะเป็นสิ่งที่ชอบ/accounts/logout/และหลังจากที่เข้าสู่ระบบผู้ใช้เขาจะถูกออกจากระบบทันที lol และลูปยังคง
hobbes3

2
ฉันพบว่าสิ่งนี้ใช้ได้เฉพาะเมื่อฉันเพิ่มสิ่งต่อไปนี้ในแบบฟอร์มการเข้าสู่ระบบบน Django 1.5: <input type = "hidden" name = "next" value = "{{next}}" />
Ellis Percival

28

นี่อาจไม่ใช่ "แนวปฏิบัติที่ดีที่สุด" แต่ฉันเคยใช้มาก่อน:

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

10
นี่เป็นจุดอ่อน - ผู้ใช้ / เบราว์เซอร์บางรายได้ปิดการอ้างอิงไปแล้ว
Tomasz Zieliński

4
นอกจากนี้ยังมีปัญหาในกรณีที่ผู้ใช้มาถึงแบบฟอร์มกรอกข้อมูลแล้วส่ง HTTP_REFERER คือ URL ของหน้าแบบฟอร์มไม่ใช่ URL ของหน้าเว็บที่ผู้ใช้มาตั้งแต่แรก
LaundroMat

25

เพื่อสนับสนุน URL แบบเต็มด้วยพารามิเตอร์ / ค่าที่คุณต้องการ:

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

แทนที่จะเป็นเพียงแค่:

?next={{ request.path }}

อันที่จริงนี่ไม่ใช่ความคิดที่ดีคุณจะพบสตริงข้อความค้นหายาวมากหากคุณมีจำนวนคลิกมากเกินไป
dspjm

14

การรับรองความถูกต้องในตัวของ Django ทำงานในแบบที่คุณต้องการ

หน้าเข้าสู่ระบบของพวกเขารวมถึงnextสตริงแบบสอบถามซึ่งเป็นหน้าเพื่อกลับไปหลังจากเข้าสู่ระบบ

ดูที่http://docs.djangoproject.com/th/dev/topics/auth/#django.contrib.auth.decorators.login_required


4
ดีมัณฑนากร login_required จะทำงานได้ดีเพราะมันตั้ง 'ถัดไป' ไปยังหน้าอะไรก็ตามที่ฉันมา แต่เมื่อใช้ผู้ใช้มัณฑนากรนิรนามไม่สามารถดูเว็บไซต์เพราะพวกเขาจะถูกเปลี่ยนเส้นทางไปยังแบบฟอร์มการเข้าสู่ระบบทันที ฉันคิดว่าฉันแค่ต้องคิดหาวิธีตั้งค่า 'ถัดไป' เป็น URL ของหน้าเว็บที่ผู้ใช้มาจาก
jörg

1

ฉันเชื่อมโยงไปยังแบบฟอร์มการเข้าสู่ระบบโดยส่งหน้าปัจจุบันเป็นพารามิเตอร์ GET แล้วใช้ 'ถัดไป' เพื่อเปลี่ยนเส้นทางไปยังหน้านั้น ขอบคุณ!


1

ฉันพบปัญหาเดียวกัน โซลูชันนี้ช่วยให้ฉันสามารถใช้มุมมองการเข้าสู่ระบบทั่วไปต่อไป:

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

1

ในregistration/login.html(ซ้อนภายในtemplatesโฟลเดอร์) หากคุณแทรกบรรทัดต่อไปนี้หน้าจะแสดงผลเหมือนหน้าเข้าสู่ระบบผู้ดูแลระบบดั้งเดิมของ Django:

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

หมายเหตุ: ไฟล์ควรมีบรรทัดด้านบนเท่านั้น


-1

ดู django docs สำหรับviews.login ()คุณให้ค่า 'ถัดไป' (เป็นฟิลด์ที่ซ่อนอยู่) ในแบบฟอร์มการป้อนข้อมูลเพื่อเปลี่ยนเส้นทางไปหลังจากการเข้าสู่ระบบที่ประสบความสำเร็จ


ใช่ แต่ฉันจะตั้ง 'ถัดไป' ให้เป็นหน้าที่ฉันมาได้อย่างไร
jörg

-3

คุณสามารถทำได้

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

คำตอบที่ไม่ถูกต้อง แต่ชื่อ = 'ถัดไป' ดูเหมือนจะเป็นไปได้ไม่ทดสอบ
WeizhongTu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.