Closed9

Djangoのチュートリアルをなぞってみる その5:ビュー作成

suzuki-navisuzuki-navi

ソースコードをす以下のように編集する。

diff --git a/mysite/polls/urls.py b/mysite/polls/urls.py
index 5119061..fc78e3e 100644
--- a/mysite/polls/urls.py
+++ b/mysite/polls/urls.py
@@ -3,5 +3,12 @@ from django.urls import path
 from . import views

 urlpatterns = [
+    # ex: /polls/
     path("", views.index, name="index"),
+    # ex: /polls/5/
+    path("<int:question_id>/", views.detail, name="detail"),
+    # ex: /polls/5/results/
+    path("<int:question_id>/results/", views.results, name="results"),
+    # ex: /polls/5/vote/
+    path("<int:question_id>/vote/", views.vote, name="vote"),
 ]
diff --git a/mysite/polls/views.py b/mysite/polls/views.py
index 963b6f7..eea456e 100644
--- a/mysite/polls/views.py
+++ b/mysite/polls/views.py
@@ -3,3 +3,13 @@ from django.http import HttpResponse

 def index(request):
     return HttpResponse("Hello, world. You're at the polls index.")
+
+def detail(request, question_id):
+    return HttpResponse("You're looking at question %s." % question_id)
+
+def results(request, question_id):
+    response = "You're looking at the results of question %s."
+    return HttpResponse(response % question_id)
+
+def vote(request, question_id):
+    return HttpResponse("You're voting on question %s." % question_id)
suzuki-navisuzuki-navi

http://localhost:8080/polls/1/results/ にブラウザでアクセスすると、 You're looking at the results of question 1. と表示される。

ちなみに http://localhost:8080/polls/1 にアクセスすると http://localhost:8080/polls/1/ に301リダイレクトされ、 You're looking at question 1. と表示される。

同様に、http://localhost:8080/polls/1/results にアクセスすると http://localhost:8080/polls/1/results/ に301リダイレクトされる。

suzuki-navisuzuki-navi

この修正をしてみる。

diff --git a/mysite/polls/views.py b/mysite/polls/views.py
index eea456e..49024f3 100644
--- a/mysite/polls/views.py
+++ b/mysite/polls/views.py
@@ -1,8 +1,10 @@
 from django.http import HttpResponse
-
+from .models import Question

 def index(request):
-    return HttpResponse("Hello, world. You're at the polls index.")
+    latest_question_list = Question.objects.order_by("-pub_date")[:5]
+    output = ", ".join([q.question_text for q in latest_question_list])
+    return HttpResponse(output)

 def detail(request, question_id):
     return HttpResponse("You're looking at question %s." % question_id)

http://localhost:8080/polls/ で最近のQuestionが5件表示されるようになる。

suzuki-navisuzuki-navi

テンプレートファイルを作成し、以下のように編集する。

diff --git a/mysite/polls/templates/polls/index.html b/mysite/polls/templates/polls/index.html
new file mode 100644
index 0000000..b2a6f93
--- /dev/null
+++ b/mysite/polls/templates/polls/index.html
@@ -0,0 +1,9 @@
+{% if latest_question_list %}
+    <ul>
+    {% for question in latest_question_list %}
+        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
+    {% endfor %}
+    </ul>
+{% else %}
+    <p>No polls are available.</p>
+{% endif %}
diff --git a/mysite/polls/views.py b/mysite/polls/views.py
index 49024f3..1152d9b 100644
--- a/mysite/polls/views.py
+++ b/mysite/polls/views.py
@@ -1,10 +1,14 @@
 from django.http import HttpResponse
+from django.template import loader
 from .models import Question

 def index(request):
     latest_question_list = Question.objects.order_by("-pub_date")[:5]
-    output = ", ".join([q.question_text for q in latest_question_list])
-    return HttpResponse(output)
+    template = loader.get_template("polls/index.html")
+    context = {
+        "latest_question_list": latest_question_list,
+    }
+    return HttpResponse(template.render(context, request))

 def detail(request, question_id):
     return HttpResponse("You're looking at question %s." % question_id)

http://localhost:8080/polls/ がテンプレートファイルで表示されるようになる。

このテンプレートだと、ブラウザにレスポンスされるHTMLにhead要素などがない。

suzuki-navisuzuki-navi

shortcutとしてpolls/views.pyに以下のように書いてもいいらしい。

from django.shortcuts import render
from .models import Question

def index(request):
    latest_question_list = Question.objects.order_by("-pub_date")[:5]
    context = {"latest_question_list": latest_question_list}
    return render(request, "polls/index.html", context)
suzuki-navisuzuki-navi

django.http.Http404をraiseすれば404になる。

diff --git a/mysite/polls/views.py b/mysite/polls/views.py
index 1152d9b..d4ccd7e 100644
--- a/mysite/polls/views.py
+++ b/mysite/polls/views.py
@@ -1,4 +1,4 @@
-from django.http import HttpResponse
+from django.http import HttpResponse, Http404
 from django.template import loader
 from .models import Question

@@ -11,7 +11,15 @@ def index(request):
     return HttpResponse(template.render(context, request))

 def detail(request, question_id):
-    return HttpResponse("You're looking at question %s." % question_id)
+    try:
+        question = Question.objects.get(pk=question_id)
+    except Question.DoesNotExist:
+        raise Http404("Question does not exist")
+    template = loader.get_template("polls/detail.html")
+    context = {
+        "question": question,
+    }
+    return HttpResponse(template.render(context, request))

 def results(request, question_id):
     response = "You're looking at the results of question %s."

suzuki-navisuzuki-navi

polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
suzuki-navisuzuki-navi

リンクのURLの賢い書き方

diff --git a/mysite/polls/templates/polls/index.html b/mysite/polls/templates/polls/index.html
index b2a6f93..4ece115 100644
--- a/mysite/polls/templates/polls/index.html
+++ b/mysite/polls/templates/polls/index.html
@@ -1,7 +1,7 @@
 {% if latest_question_list %}
     <ul>
     {% for question in latest_question_list %}
-        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
+        <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
     {% endfor %}
     </ul>
 {% else %}
このスクラップは2023/08/06にクローズされました