kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

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_tokenCSRFを防ぐものらしい
ここでは、とにかくフォームには入れとけというくらいの説明だけ
こんな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に戻った
これがリダイレクトの効能かな