Menu
CoddyTech

Chuyển hướng sau POST

Thuộc phần Biểu mẫu trong hành trình Django của Coddy. Bài học 3 trên 20.

Thêm một sự kiện, rồi tải lại trang cảm ơn: trình duyệt đề nghị gửi lại biểu mẫu, và nếu bạn đồng ý, sự kiện sẽ được thêm hai lần. Trang đó là phản hồi cho một POST, vì vậy khi tải lại, trình duyệt sẽ gửi lại POST.

Cách khắc phục là một mẫu thiết kế có tên là Post/Redirect/Get. Sau khi lưu, hàm xử lý phản hồi bằng một chuyển hướng: mã trạng thái 302 và một địa chỉ mới. Trình duyệt mở địa chỉ đó bằng GET, vì vậy khi tải lại, trình duyệt chỉ gửi lại GET.

redirect() từ django.shortcuts nhận tên URL, giống như {% url %}. Ví dụ về một cửa hàng thêm mặt hàng vào giỏ:

from django.shortcuts import redirect


def add_to_cart(request, pk):
    if request.method == "POST":
        CartItem.objects.create(product_id=pk)
        return redirect("shop:cart")
    ...

Với URL có tham số, hãy truyền tham số theo tên: redirect("shop:product", pk=7).

challenge icon

Thử thách

Dễ

Trong new_event, sau khi tạo sự kiện, hãy chuyển hướng đến trang riêng của sự kiện mới thay vì kết xuất event_added.html. Bạn có thể xóa event_added.html; giờ không có gì dùng tệp này nữa.

Thêm một sự kiện, rồi tải lại trang của sự kiện đó: trình duyệt không yêu cầu gửi lại biểu mẫu.

Tự làm thử

from django.shortcuts import get_object_or_404, render

from .models import Event


def event_list(request):
    q = request.GET.get("q", "")
    events = Event.objects.all()
    if q:
        events = events.filter(title__icontains=q)
    return render(request, "events/event_list.html", {"events": events, "q": q})


def event_detail(request, pk):
    event = get_object_or_404(Event, pk=pk)
    return render(request, "events/event_detail.html", {"event": event})


def new_event(request):
    if request.method == "POST":
        Event.objects.create(
            title=request.POST["title"],
            date=request.POST["date"],
            place=request.POST["place"],
        )
        return render(request, "events/event_added.html")
    return render(request, "events/new_event.html")

Tất cả bài học trong Biểu mẫu

Tự luyện tập: Playground Django