▶ ユーザー画面の作成の仕組みについてはこちらの投稿がご覧ください。
はじめに
前回は、URLが指定された時の処理について扱いました。まずプロジェクトが振り分けをおこなって、appが呼び出された場合はapp内で処理をおこなうのでしたね。その際にテンプレートが呼ばれるので、前回はそこに空っぽのindex.htmlをおくところまで扱いました。djangoではHTMLファイルに変数の中身を表示したり、条件分岐などのロジックを埋め込むことができます。これはテンプレートという仕組みで実現しています。今回は、テンプレートに変更を加えて画面を作りこんでいきます。
テンプレート
djangoでは、テンプレートエンジンとして「DTL(Django Template Languate)」を利用することができます。
DTL記法では、テンプレートタグを使って、指定した箇所の内容を置き換えたり、変数の内容を表示することができます。
テンプレートタグはテンプレートの機能を拡張するための記法です。タグの開始と終了を指定します。よく使うのは次のようなものです。
- if
- for
- block
それぞれみていきましょう。
if(条件分岐)
「{% if … %}」 「{% elif … %}」 「{% else … %}」 「{% endif %}」というタグを利用して条件に合わせた表示の切り替えができます。「if」「elif」「else」を使うのは通常のPythonの構文と同じですが、最後に「endif」をつける必要があるのが注意点です。また、それぞれのタグの内部の末尾に「:」をつけない、という点も気を付けてください。
for(ループ)
「{% for … %}」と「{% endfor %}」で囲まれた範囲をループさせることができます。変数が存在しない、あるいは変数の値が空のリストでループが回せない場合に表示する内容を記述するための「empty」タグを」併用すると、便利に使えることがあります。
{% for question in question_list %}
{{ question.question_text }}
{% empty %}
質問はありません
{% endfor %}
block(オーバーライド対象のブロック)
「{% block <任意の名前>%}」と「{% endblock %}」で囲まれた範囲(ブロック)に任意の名前を付けて、継承関係のある子テンプレートから内容の上書きができるようにするためのタグです。
変数表示
変数は、二重の中括弧{{ }}で囲むことで表示することができます。
テンプレートを編集する
それではユーザー画面をつくっていきましょう。まだ何も書かれていない状態でしたね。まずは、すべてのベースとなる、基本レイアウトなどを記述したbase.htmlを作成しておくとよいでしょう。
base.html
(pollster/templates/base.html)
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<title>投票画面 {% block title %}{% endblock %}</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 m-auto">
{% block content %}{% endblock %}
</div>
</div>
</div>
</body>
</html>
ここは、普通にHTMLを作成して、ページによって内容を置き換えたい箇所をblockタグとしておきます。ここでは、titleとcontentにブロックタグを入れてみました。
index.html
{% extends 'base.html' %}
{% block title %}
インデックス
{% endblock %}
{% block content %}
{% block content %}
投票画面
{%endblock%}
「extends」タグを利用することで別のテンプレートをベースにして必要な部分だけ書き換えることができます。ここでは、「base.html」を指定しています。
次に「block」タグを使って、置き換える部分の記述をしています。今回は、タイトルの一部とコンテンツ部分を書き換えています。
このようにタイトルが「投票画面インデックス」、コンテンツが「投票画面」となっていれば成功です。base.htmlでタイトル部分は、「投票画面 {% block title %}{% endblock %}」と書いているので、「投票画面」の部分は固定で、そのあとのブロック変数部分に「インデックス」との置き換えを指示したので、タイトルは「投票画面インデックス」となります。
さらにindex.htmlの編集を続けていきましょう。pollsのindex.htmlでは、質問の一覧を表示させます。そこで、index.htmlを次のようにします。
(pollster/polls/index.html)
{% extends 'base.html' %}
{% block content %}
<h1 class="class text-center mb-3">質問</h1>
{% if question_list %}
{% for question in question_list %}
<div class="card mb-3">
<div class="crd-body">
<p class="lead">{{ question.question_text }}</p>
</div>
</div>
{% endfor %}
{%else%}
<p>質問項目はありません</p>
{% endif %}
{%endblock%}
ここでDTL記法のif文、for文がでてきます。まず、「{% if question_list %}% if question_list %}」は「question_list」が存在すれば、の意味になります。
続いて、「{% for question in question_list %}」の部分は、「question_list」から「question」を一つずつ取り出しています。最終的に、この「question」から「question.question_text」を表示させる、ということを繰り返す記述になっています。
さて、これでquestionを表示する設定をindex.html側に記述することができました。ただ、index.htmlに「question_list」を渡す設定ができていません。pollster/polls/index.htmlを呼び出すのは、pollster/polls/views.pyでしたね。現在は、次のような記述になっています。
(pollster/polls/views.py)
from django.shortcuts import render
from .models import Question, Choice
# 質問を取得し、それを表示する
def index(request):
return render(request, 'polls/index.html')
views.indexが呼ばれても、質問を取得して返す、という処理がかかれていませんね。ここを編集していきましょう。次のようにします。
(pollster/polls/views.py)
from django.shortcuts import render
from .models import Question, Choice
def index(request):
question_list = Question.objects.all().order_by('-pub_date')
context = {'question_list':question_list}
return render(request, 'polls/index.html',context)
「question_list = Question.objects.all().order_by(‘-pub_date’)」のところで、Questionのオブジェクトからすべてのデータを引っ張ってきて、「pub_date」を新しいもの順に並べています。次に、テンプレートにデータを渡すには、辞書型で渡す必要があるため、辞書を作ります。このようなファイルをコンテキストファイルと呼ぶため、変数名を「context」としておきます。「context = {‘question_list’:question_list}」は、テンプレートの中で使う変数名をkeyに、実際のデータをvalueとします。最後に、renderの第3引数としてcontextを渡すようにします。
すると次のように表示されます。
これで質問のリストが表示されるようになりました。今回はここまでにしましょう。
まとめ
いかがでしたか?実はここまで辿り着くのに、たくさんのエラーを引き起こしました。フレームワークで楽にしてくれているとはいえ、初めてだとなかなか難しいですね。次回は、「投票」ボタンをつけて、実際に投票を受け付けられるようにします。
▶ djangoの簡単なまとめ記事もあります。
コメント