Closed7
Djangoのチュートリアルをなぞってみる その6:フォーム
前回のスクラップの続き
Django公式チュートリアルをなぞっています。
今回は以下のページです。
どこかでチュートリアルの手順を飛ばしたのか、Choice
にレコードがないので、管理画面からレコードを登録する。そのために以下の修正をする。
diff --git a/mysite/polls/admin.py b/mysite/polls/admin.py
index 6af8ff6..f191ae3 100644
--- a/mysite/polls/admin.py
+++ b/mysite/polls/admin.py
@@ -1,5 +1,6 @@
from django.contrib import admin
-from .models import Question
+from . import models
-admin.site.register(Question)
+admin.site.register(models.Question)
+admin.site.register(models.Choice)
以下のようにform要素を書く。
diff --git a/mysite/polls/templates/polls/detail.html b/mysite/polls/templates/polls/detail.html
index 975db2a..bfe30b3 100644
--- a/mysite/polls/templates/polls/detail.html
+++ b/mysite/polls/templates/polls/detail.html
@@ -1,6 +1,12 @@
-<h1>{{ question.question_text }}</h1>
-<ul>
-{% for choice in question.choice_set.all %}
- <li>{{ choice.choice_text }}</li>
-{% endfor %}
-</ul>
+<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>
diff --git a/mysite/polls/urls.py b/mysite/polls/urls.py
index fc78e3e..b121783 100644
--- a/mysite/polls/urls.py
+++ b/mysite/polls/urls.py
@@ -2,6 +2,7 @@ from django.urls import path
from . import views
+app_name = "polls"
urlpatterns = [
# ex: /polls/
path("", views.index, name="index"),
ブラウザでアクセスすると、こんなHTMLソースになっている。
<form action="/polls/1/vote/" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="NGmB0zNVvOfsTcUIhRTsaJ5XNqAieLKX5HvoEC70J7A75QUQ5xINnjyzSYTqdGt2">
<fieldset>
<legend><h1>What's up??</h1></legend>
<input type="radio" name="choice" id="choice1" value="1">
<label for="choice1">OK</label><br>
<input type="radio" name="choice" id="choice2" value="2">
<label for="choice2">No Good</label><br>
</fieldset>
<input type="submit" value="Vote">
</form>
投票のPOST先を実装する。
diff --git a/mysite/polls/views.py b/mysite/polls/views.py
index d4ccd7e..d5d0943 100644
--- a/mysite/polls/views.py
+++ b/mysite/polls/views.py
@@ -1,6 +1,8 @@
-from django.http import HttpResponse, Http404
+from django.http import HttpResponse, Http404, HttpResponseRedirect
+from django.shortcuts import get_object_or_404, render
from django.template import loader
-from .models import Question
+from django.urls import reverse
+from .models import Question, Choice
def index(request):
latest_question_list = Question.objects.order_by("-pub_date")[:5]
@@ -26,4 +28,24 @@ def results(request, question_id):
return HttpResponse(response % question_id)
def vote(request, question_id):
- return HttpResponse("You're voting on question %s." % 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,)))
votesの値を取得してから1加算した値を保存しているので、同時アクセスしたらおかしくなりうる。
投票結果のページを実装
diff --git a/mysite/polls/templates/polls/results.html b/mysite/polls/templates/polls/results.html
new file mode 100644
index 0000000..3b2c74f
--- /dev/null
+++ b/mysite/polls/templates/polls/results.html
@@ -0,0 +1,9 @@
+<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>
diff --git a/mysite/polls/views.py b/mysite/polls/views.py
index d5d0943..29204d6 100644
--- a/mysite/polls/views.py
+++ b/mysite/polls/views.py
@@ -24,8 +24,8 @@ def detail(request, question_id):
return HttpResponse(template.render(context, request))
def results(request, question_id):
- response = "You're looking at the results of question %s."
- return HttpResponse(response % question_id)
+ question = get_object_or_404(Question, pk=question_id)
+ return render(request, "polls/results.html", {"question": question})
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
viewにpluralize
という記述があるが、自動で英語の複数形にしてくれるようである。
単語によって複数形を使い分けてくれるわけではなく、s
以外の場合は接尾辞を指定する必要がある。
walrus{{ num_walruses|pluralize:"es" }}.
cherr{{ num_cherries|pluralize:"y,ies" }}.
Viewの実装をより簡潔に書く方法
このスクラップは2023/08/06にクローズされました