English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
フォーム 前節のチュートリアルで、私たちはDjangoのビュー
poll detail テンプレートを更新しましょう(「polls」/detail.html) ,前のチュートリアルから、テンプレート polls/templates/polls/detail.html にHTML<form>要素が含まれています:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ja.oldtoolbag.com # Date : 2020-08-08 <h1>{{ question.question_text }}</h1> {% if error_message %}<p><strong>{{ error_message }}<//strong></p>{% endif %} <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="投票" /> </form>上のテンプレートは、各問題に対して1つのオプションを選択するために単一選択ボックスを表示します。各単一選択ボックスの値は、関連する問題の選択番号に関連付けられています。各単一選択ボックスの名前は「choice」です。これは、誰かが1つの単一選択ボックスを選択しフォームを提出すると、POSTデータchoice=#が送信されることを意味します、ここで#は選択された選択のIDです。これはHTMLフォームの基本的な概念です。 私たちはフォームのアクション{% url 'polls:vote' question.id %}を設定し、method="post"を設定します。method="post"(method="get"に比べて)を使用することは非常に重要です、なぜなら、このフォームを提出すると、サーバー側のデータの行動が変更されるからです。データを変更するサーバー側のフォームを作成する場合、method="post"を使用します。これはDjangoに特化したものではなく、優れたWeb開発の慣習です。 forloop.counterは、フォームタグが何回ループを通過したかを示します。 POST形式(データの変更に影響を与える可能性があります)を作成しているため、クロスサイトリクエストフォージェリーに注意する必要があります。しかし、心配しないでください、Djangoは非常に使いやすいシステムを提供しています。要するに、内部URLに対するすべてのPOST形式では、{%csrf_token%}テンプレートタグを使用する必要があります。
私たちは仮実装の vote() 関数を作成しました。実際のバージョンを作成するために以下のコードを polls ファイルに追加します。/views.py:
polls/views.py ファイルの内容如下:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ja.oldtoolbag.com # Date : 2020-08-08 from django.shortcuts import get_object_or_404, render from django.http import HttpResponseRedirect, HttpResponse from django.core.urlresolvers 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): # 問題投票フォームを再表示します。 return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", ) else: selected_choice.votes += 1 selected_choice.save() # データを正常に処理した後は常にHttpResponseRedirectを返します。 # POSTデータで。これにより、データが再度投稿されないことを防ぎます。 # ユーザーがBackボタンをクリック。 return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
このコードには、本教程でまだ取り上げられていないいくつかの要素が含まれています:
request.POSTは辞書に似たオブジェクトで、キー名を使用して提出されたデータにアクセスできます。この場合、request.POST['choice']は選択された選択肢のIDを文字列として返します。request.POSTの値は常に文字列です。
注意:Djangoはrequest.GETを同じ方法でGETデータにアクセスを提供しますが、私たちのコードでは明示的にrequest.POSTを使用し、データがPOSTコールのみを通じて変更されることを確実にします。
POSTデータにchoiceが提供されていない場合、request.POST['choice']はKeyError例外を発生させます。上記のコードはKeyError例外とエラーメッセージを表示するフォームをチェックし、choiceが指定されていない場合があります。
選択肢のカウントが増えた後、コードはHttpResponse重定向を返し、通常のHttpResponseではなくなります。HttpResponseRedirectにはパラメータが必要で、ユーザーがリダイレクトされるURLが必要です(以下を参照してください。-このような状況での URL をどのように構築するか)。
Pythonのコメントに示されるように、POST データの処理が成功した後は、常に HttpResponseRedirect を返す必要があります。
このサンプルでは、HttpRedirectResponse コンストラクタと reverse() 関数を使用しています。この関数は、ビュー内でハードコーディングされた URL を避けるのに役立ちます。なぜなら、URL モードの可変部分を指し示すビューの名前を制御して、reverse() 呼び出しから文字列を返す URLconf 設定を使用したいからです。この場合、reverse() 呼び出しは以下のようになります:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ja.oldtoolbag.com # Date : 2020-08-08 '/polls/3/results/'
その中で3question.idの値です。その後、このリダイレクトのURLは、'results' ビューが表示する最後のページを呼び出します。
現在、URLをアクセスします:http://127.0.0.1:8000/polls/1/ 得られた結果は以下の通りです: 当有人在一个问题投票后,vote() ビューがその問題の結果ページにリダイレクトします。このビューを書いてみましょう(polls/views.py):
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ja.oldtoolbag.com # Date : 2020-08-08 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})
现在,创建一个 polls/results.html (polls/templates/polls/results.html)テンプレート:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ja.oldtoolbag.com # Date : 2020-08-08 <h2>{{ question.question_text }}</h2> <ul> {% for choice in question.choice_set.all %} <li>{{ choice.choice_text }} -- {{ choice.votes }} 投票{{ choice.votes|pluralize }}</li> {% endfor %} </ul> <a href="{% url 'polls:detail' question.id %}">もう一度投票?</a>
今、ブラウザで以下を開きます /polls/1/ 投票に表决された問題。投票時に更新された結果ページが表示されるべきです。フォームを提出してオプションを選択しない場合、エラーメッセージが表示されるべきです。オプションを選択して提出すると、以下のような結果が表示されます:
まず、polls/urls.py を以下のように修正します:
from django.conf.urls import url from . import views app_name = 'polls' urlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'), url(r'^(?P<pk>[0-9]+)/$, views.DetailView.as_view(), name='detail'), url(r'^(?P<pk>[0-9]+)/results/$, views.ResultsView.as_view(), name='results'), url(r'^(?P<question_id>[0-9]+)/vote/$, views.vote, name='vote'), ]