Menu
CoddyTech

POST 后重定向

本课属于 Coddy Django 学习旅程的“表单”单元。第 3 课,共 20 课。

添加一个活动,然后重新加载感谢页面:浏览器会询问是否重新发送表单,同意后会重复添加该活动。该页面是对 POST 的响应,因此重新加载时会再次发送 POST。

解决方法是一种叫作 Post/Redirect/Get 的模式。保存后,视图会返回一个重定向:状态码 302 和一个新地址。浏览器会使用 GET 打开该地址,因此重新加载时只会重复发送 GET。

redirect() 来自 django.shortcuts,它接收一个 URL 名称,和 {% url %} 的用法相同。下面是一个将商品添加到购物车的示例:

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

如果 URL 带有参数,可以按名称传入:redirect("shop:product", pk=7)。

challenge icon

挑战

简单

在 new_event 中,创建活动后,重定向到该活动自己的页面,而不是渲染 event_added.html。你现在可以删除 event_added.html,因为已经没有任何地方会用到它。

添加活动,然后重新加载它的页面:浏览器不会再询问你是否要重新发送表单。

亲手试试

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

表单中的所有课

自己练习: Django 在线编辑器