9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Django+Reactで学ぶプログラミング基礎(8): Djangoチュートリアル(投票アプリその4-1)

Last updated at Posted at 2022-06-07
[前回] Django+Reactで学ぶプログラミング基礎(7): Djangoチュートリアル(投票アプリその3)

はじめに

Django公式チュートリアル、その4-1です。
前回は、Djangoビューを深掘りしました。
今回は、フォームを作成してみます。

Djangoアプリ作成(その4-1): 投票(poll)アプリ

今回の内容

  • フォームを作成

フォームを書く

  • 投票詳細テンプレートにHTMLの<form>要素を追加
    • 各質問の選択肢のラジオボタンが表示される
      • 各ラジオボタンのvalueは、質問選択肢のID
      • 各ラジオボタンのnamechoice
      • 投票者がラジオボタンの1つを選択し、フォームを送信すると
        • POSTデータchoice=#(#は選んだ選択肢のID)が送信される
  • クロスサイトリクエストフォージェリ(CSRF)によるデータ改ざんに、POSTフォームが悪用されないように
    • 自サイト内をURLに指定したPOSTフォームには、全て{% csrf_token %}テンプレートタグを使う
    • CSRFとは、Webアプリケーションに存在する脆弱性、もしくはその脆弱性を利用した攻撃方法
polls/templates/polls/detail.html
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% 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 %}
</fieldset>
<input type="submit" value="Vote">
</form>

image.png

vote()ビューを作成し、フォームの送信データを処理

  • request.POST
    • 辞書オブジェクトで、キーを指定すると、送信データにアクセスできる
    • request.POST['choice']は、選択された選択肢のIDを文字列として返す
      • request.POSTの値は常に文字列
      • POSTデータにchoiceがなければ、KeyErrorを返却
  • HttpResponseRedirect
    • 別のURLにリダイレクトする関数
    • コンストラクタの中でreverse()関数を使用し、ビュー関数中でURLのハードコードを防ぐ
      • 関数の引数
        • 制御を渡したいビューの名前
        • ビューに与えるURLパターンの位置引数
      • 例では、reverse()を呼ぶと、URLconf指定とおり、次のような文字列が返される
        • /polls/3/results/(3はquestion.idの値)
    • リダイレクト先のURLは、resultsビューを呼び出し、最終的なページにリダイレクト
polls/views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from .models import Choice, Question
# ...
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):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

質問の結果result()ビューの作成

  • 誰かが質問の投票すると、vote()ビューは質問の結果ページにリダイレクト
polls/views.py
from django.shortcuts import get_object_or_404, render


def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

image.png

  • result()ビューのテンプレートを作成
polls/templates/polls/results.html
<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

管理サイトで質問の選択肢を登録

  • 管理サイトにChoiceモデルを登録
polls/admin.py
from random import choices
from django.contrib import admin

from .models import Question,Choice

admin.site.register(Question)
admin.site.register(Choice)
  • VS Codeターミナルで、仮想環境をアクティベート
C:\kanban\pollsite>..\venv\.venv\Scripts\activate
  • 開発サーバーを起動
(venv) C:\kanban\pollsite>python manage.py runserver
  • 管理サイトhttp://127.0.0.1:8000/admin/にログインし、質問1の選択肢を追加
    image.png

投票してみる

  • ブラウザでhttp://127.0.0.1:8000/polls/1/にアクセス

image.png

  • 票を入れるたびに、結果のページが更新される
    • 選択肢を選ばずにフォームを送信すると、エラーメッセージが表示される

image.png

おわりに

Djangoアプリにフォームを追加し、投票を行いました。
次回も続きます。お楽しみに。

[次回] Django+Reactで学ぶプログラミング基礎(9): Djangoチュートリアル(投票アプリその4-2)
9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?