もた日記

くだらないことを真面目にやる

Djangoメモ(8) : テンプレートを使った表示

Python 3.6.4 Django 2.0.2

A Complete Beginner's Guide to Djangoのチュートリアルを参考にテンプレートを作成してみる。


ビューを編集

前回まででモデルの作成とデータの登録は完了しているのでウェブページとしてデータを表示してみる。
Hello, World!を表示するようになっているboards/views.pyを以下のように編集する。

変更前

from django.http import HttpResponse

def home(request):
    return HttpResponse('Hello, World!')

変更後

from django.http import HttpResponse
from .models import Board

def home(request):
    boards = Board.objects.all()
    boards_names = list()

    for board in boards:
        boards_names.append(board.name)

    response_html = '<br>'.join(boards_names)

    return HttpResponse(response_html)

これでシンプルなウェブページとしてデータが表示される。

f:id:wonder-wall:20180308105721p:plain


テンプレートを作成

上記のようにboards/views.pyにページのレイアウトも記述することはできるが、ページのレイアウトを変更しやすいようにDjangoのテンプレートシステムを使ってビューから使用できるテンプレートを作成する。
最初にmanage.pyと同じ階層にtemplatesディレクトリを作成する。

myproject
├── myproject
│  ├── boards
│  ├── db.sqlite3
│  ├── manage.py
│  ├── myproject
│  └── templates  # mkdirで作成
├── Pipfile
└── Pipfile.lock

次に下記内容のtemplates/home.htmlファイルを作成する。
大部分は通常のHTMLだが{%, %}{{, }}で囲まれた部分がテンプレート言語で、この部分が動的に置き換えられてHTMLが生成される。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Boards</title>
  </head>
  <body>
    <h1>Boards</h1>

    {% for board in boards %}
      {{ board.name }} <br>
    {% endfor %}

  </body>
</html>

作成したテンプレートを検索対象とするためにsettings.pyファイルのTEMPLATES'DIRS': [],部分を編集する。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates')
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

テンプレートを呼ぶようにboards/views.pyを再編集する。
render()関数の説明は下記。

render() 関数は、第1引数として request オブジェクトを、第2引数としてテンプレート名を、第3引数(任意)として辞書を受け取ります。この関数はテンプレートを指定のコンテキストでレンダリングし、その HttpResponse オブジェクトを返します。

from django.shortcuts import render
from .models import Board

def home(request):
    boards = Board.objects.all()
    return render(request, 'home.html', {'boards': boards})

f:id:wonder-wall:20180308110817p:plain

これでテンプレートを使った表示が確認できた。
表示がシンプルなのでtemplates/home.htmlを編集して表組みにする。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Boards</title>
  </head>
  <body>
    <h1>Boards</h1>

    <table border="1">
      <thead>
        <tr>
          <th>Board</th>
          <th>Posts</th>
          <th>Topics</th>
          <th>Last Post</th>
        </tr>
      </thead>
      <tbody>
        {% for board in boards %}
          <tr>
            <td>
              {{ board.name }}<br>
              <small style="color: #888">{{ board.description }}</small>
            </td>
            <td>0</td>
            <td>0</td>
            <td></td>
          </tr>
        {% endfor %}
      </tbody>
    </table>
  </body>
</html>

f:id:wonder-wall:20180308110956p:plain


テンプレート言語

テンプレート言語についてドキュメントを参考に簡単に調べてみる。

変数

変数は{{, }}で囲まれたもので、テンプレートに渡された変数が{'first_name': 'John', 'last_name': 'Doe'}の場合は、

My first name is {{ first_name }}. My last name is {{ last_name }}.

My first name is John. My last name is Doe.

と表示される。 辞書、オブジェクト、リストについては以下のようにアクセスできる。

{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}

タグ

タグは{%, %}で囲まれたものでfor文やif文などがある。
以下のように引数を取るタグや、

{% cycle 'odd' 'even' %}

if, endifのように始まりと終わりを必要とするタグがある。

{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}

詳しくはドキュメントの組み込みタグを参照。

フィルター

|upperのようなパイプを使った表現がフィルタで、この場合は変数の値がDjangoだと全部大文字のDJANGOに変換されて表示される。

{{ board.name|upper }}

以下のように引数を取ったり、複数のフィルタを繋げることもできるようだ。

{{ my_date|date:"Y-m-d" }}

詳しくはドキュメントの組み込みフィルタを参照。

コメント

{#, #}で囲むとコメントになる。

{# this won't be rendered #}

複数行のコメントは下記タグを使用する。

{% comment %}
ここはコメント
ここはコメント
{% endcomment %}


まとめ

  • ウェブページの表示部分はテンプレートを使う
  • テンプレートの追加はsettings.pyTEMPLATESを編集
  • テンプレートの表示はrender()関数を使用
  • テンプレート言語には変数、タグ、ファイルターなどがある