Djangoチュートリアル(9) フォーム
今日はフォーム
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}"/>
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br/>
{%endfor%}
<input type="submit" value="Vote" />
</form>
サーバ側のデータを更新するフォームを作成する場合は、 method="post" を使いましょう。これは、 Django 固有のものではなく、いわば Web 開発の王道です。
これはRESTの話で出てくるやつかな
csrf_token
はCSRFを防ぐものらしい
ここでは、とにかくフォームには入れとけというくらいの説明だけ
こんなHTMLになった
<form action="/polls/3/vote/" method="post">
<input type='hidden' name='csrfmiddlewaretoken' value='XDHXvphEeG6LkkUff1HqVJxaEU1HwW6cRuqIbK4sK8C8TqlMjr6f9lLsCpwzDfZ4' />
<input type="radio" name="choice" id="choice1" value="5"/>
<label for="choice1">Blue</label><br/>
<input type="radio" name="choice" id="choice2" value="6"/>
<label for="choice2">Red</label><br/>
<input type="radio" name="choice" id="choice3" value="7"/>
<label for="choice3">Green</label><br/>
<input type="submit" value="Vote" />
</form>
csrfmiddlewaretoken
ってやつでおかしなとこからのアクセスじゃ
ないですよって証明するわけだな
views.vote
は全面書き直し
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice."})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
request.POST['choice']
でPOSTされたデータのchoice
の値が取れる
choice
自体がなければKeyError
で
choice
はあるけど該当する値がなければDoesNotExist
ってことだな
エラーだったらerror_message
を設定して再度detail.htmlを表示
ちゃんとしたchoice
があったらデータベースを更新してresult
のページを表示
POST データが成功した後は常に HttpResponseRedirect を返す必要があります。これは Django 固有のものではなく、 Web 開発における良いプラクティスです。
戻るボタンを押した時にもう一度投票されたりしないようになるらしい
へー
Voteボタンを押すとこんなログが出てる
voteに一瞬アクセスしてすぐにresultsにリダイレクトされてる
[05/Jul/2019 13:14:32] "POST /polls/3/vote/ HTTP/1.1" 302 0
[05/Jul/2019 13:14:32] "GET /polls/3/results/ HTTP/1.1" 200 44
resultsのページで戻るボタンを押すとdetail.htmlに戻った
これがリダイレクトの効能かな