POST後のリダイレクト
CoddyのDjangoジャーニー「フォーム」セクションの一部。レッスン 3/20。
イベントを追加してからサンクスページを再読み込みすると、ブラウザーはフォームを再送信するかどうかを尋ね、同意するとイベントが2回追加されます。このページはPOSTに応答するため、再読み込みするとPOSTが繰り返されます。
この問題を解決するのが、POST/Redirect/GETと呼ばれるパターンです。保存後、ビューはリダイレクトで応答します。ステータスは302で、新しいアドレスが指定されます。ブラウザーはそのアドレスをGETで開くため、再読み込みしてもGETだけが繰り返されます。
django.shortcutsのredirect()には、{% 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)。
チャレンジ
簡単new_eventでイベントを作成した後、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プレイグラウンド