Web

Python初心者向け:django~ユーザー画面の作成②~

スポンサーリンク


▶ ユーザー画面の作成の仕組みについてはこちらの投稿がご覧ください。

はじめに

前回は、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の簡単なまとめ記事もあります。

コメント

タイトルとURLをコピーしました