pyhaya’s diary

プログラミング、特にPythonについての記事を書きます。Djangoや機械学習などホットな話題をわかりやすく説明していきたいと思います。

Djangoのチュートリアル 4 HTMLに慣れる

Djangoチュートリアルの第4弾です。過去の記事はこちらです。
Djangoのチュートリアル 1 インストールから最初のビュー作成まで - pyhaya’s diary
Djangoのチュートリアル 2 モデルを作成する - pyhaya’s diary
pyhaya.hatenablog.com

前回は、DjangoでのWebページのデザインに限界を感じ、HTMLによる記述に心移りするところまで行きました。正直私は今までバックエンドの勉強ばかりでWebページのようなフロントエンドはさぼってきました。なので、ここで少しHTMLの練習もかねて、ビューのindexが呼ばれたときに表示されるページを編集してみようと思います。

ただし、必要最低限です。あまり作りこんだりCSSとか編集しだしたら初心者にはわかりにくい記事になってしまうし、何より私が把握できなくなりますww。

目次

何を作るか

前回の記事では、データベースに登録していたQuestionをindex.htmlに表示させるところまで書きました。ここで、各Questionにはリンクが張られていてクリックすると「Hello, World. This is polls application number 1」とかQuestionのIDが表示されていました。

今回編集するのは、この、クリックしたときに飛ぶページです。前回まではビューのdetailにべた書きしてました。これをHTMLに任せようと思います。具体的にこのページは何を表示すべきでしょうか?Questionをクリックして飛んでくるので、以下のようなページがよさそうです。

  • クリックされたQuestionに対する選択肢(Choiceをmodels.pyに作ったのを覚えているでしょうか)が表示される
  • Questionがページ上部に大きく表示される

ビューを編集する

では、index関数を参考にdetail関数を作ってみます。

polls/views.py

from django.shortcuts import render

from .models import Question

# Create your views here.
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)

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

detailでは、Questionをコンテクストとして与えてdetail.htmlに渡します。これを受け取ったdetail.htmlは、Questionをもとに、そこに紐づけられている選択肢を取得し、表示します。この時、detail.htmlは、

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
    </head>
    <body>
        <h1>{{ question.question_text }} </h1>
        {% for choice in question.choice_set.all %}
        <li>{{ choice.choice_text }}</li>
        {% endfor %}
    </body>
</html>

質問文であるquestion_textはh1タグを付けてでかでかと表示します。次は、紐づけられている選択肢を表示します。これにはfor文を用いるのが良いでしょう。HTML内でfor文を使うときには{% %}で囲み、最後には{% endfor %}を付けるのでした。

choice_setというのはここではじめてあらわれました。これについて少し書いておきます。

choice_setとは?

せっかくなのでここでモデルどうしの関係性を整理しておきます。下の図を見てください。
f:id:pyhaya:20181030223042p:plain
一番左がユーザー、というかプログラマで、プログラマQuestionモデルを見ています。Questionのオブジェクトは、Question.objectsとして存在しています。Questionオブジェクトが全部ほしいときにはプログラマ

Question.objects.all()

と書くことで全部取得できます。

各QuestionオブジェクトにはそれぞれいくつかのChoiceオブジェクトが紐づけられています。ここではQuestion1, Question2にそれぞれChoice1-1やChoice2-1などが紐づけられています。ここでQuestion1に紐づけられているChoiceはQuestion1.choice_setに入っています。これを取り出したかったら

Question1.choice_set.all()

とすることで全部取得できます。ここで、choice_setという名前ですが、これがDjangoの提供するメソッドの名前そのものというわけではなくて、Questionに紐づけられているのがChoiceだからこれを小文字にして_setを付けているだけです。だからQuestionに紐づけられているクラスの名前がfooだったらこれはfoo_setとします。これは次のやり取りが参考になると思います。
stackoverflow.com

Webページを表示してみる

ではサーバーを動かしてページを見てみましょう。
http://127.0.0.1:8000/pollsを見てみると、登録したQuestionの一覧が出てきて、一つクリックすると質問文が大きく表示され、、、その下には何も表示されていません。そういえばChoiceは一つも登録していませんでした。polls/admin.pyにChoiceを登録して
http://127.0.0.1:8000/adminページからChoiceをいくつか登録してみます。

polls/admin.py

from django.contrib import admin
from .models import Question, Choice

# Register your models here.
admin.site.register(Question)
admin.site.register(Choice)

これで質問文の下に選択肢が表示されるようになります。

まとめ

今回はここまでです。今回やったことは

  • HTMLの練習をした
  • Choiceのデータを取り出す方法を学んだ

です。