【Python Django】初心者プログラマーのWebアプリ#2 HTMLテンプレート表示

# Python DjangoフレームワークでHTML表示

[前回](https://qiita.com/Bashi50/items/c686d30fa4fdba4582ad)の簡単な文字表示アプリ記事の続きです。
Hello World!と表示させた超基礎内容でした。
今回は、pythonで処理した内容をキレイにブラウザで表示させるための基礎として**HTML**に記述することで表現の幅を広げます。
![logo.png](https://qiita-image-store.s3.amazonaws.com/0/260345/bc82f6d1-cf2b-843a-fd6b-e54933457f73.png)

:::note info
内容が古くなったのでDjango 3で記事更新しました。 updated: 2021/09
:::

# :pushpin: Pythonで作るDjangoアプリ記事一覧

|  | 内容|
|:----:|:----:|
|**part1**|[簡単な文字表示アプリを作る](https://qiita.com/Bashi50/items/c686d30fa4fdba4582ad)|
|**part2**|**HTMLテンプレート表示　← ココ**|
|**part3**|["画像" "CSS" "Javascript"実装](https://qiita.com/Bashi50/items/3452bd1692fdd0ac6392)|
|**part4**|[フォーム送信](https://qiita.com/Bashi50/items/93da7a071b2e02dc21ed)|
|**part5**|[データベースの値取得・更新](https://qiita.com/Bashi50/items/280bc341eeec5d7f8797)|
|**番外編**|[Django AWS デプロイ](https://qiita.com/Bashi50/items/d5bc47eeb9668304aaa2)|
|**APIサーバー編**|[Django REST frameworkとReact #4](https://qiita.com/Bashi50/items/203505440049d759b694)|
|**単体テスト編**|[Django unittestで単体テスト](https://qiita.com/Bashi50/items/4205c398f475bc69f631)|

# HTMLテンプレートでWEBページを作る
WEBアプリを作るための最初のステップとしてHTMLから始めた人は多いのではないでしょうか？
DjangoでもHTMLテンプレートというのを使っていて、サーバーに保存されているデータや、なにかしらの計算をしてページを作る（動的に作るという）ことができます。

## ソースコード
この章のコードは以下です。確認やコピペでどうぞ

https://github.com/kohishibashi/easy-django/tree/part2

## HTMLファイルを作成
前回文字を固定で表示させることはできましたが、毎回同じ表示をするようなアプリではDjango使う意味ないですよね。
ということでHTMLテンプレートを使って柔軟に表示をさせるのは必要不可欠です。とうことでブラウザに表示させるための基礎となるhtmlファイルを作成していきます。

基本的にはHTMLで、データを埋め込むための記法を使うことができるという感じです。

### フォルダ、ファイルの作成
templateフォルダをアプリケーションフォルダ内に作成。

`C:\Users\○○○\django\testproject\webtestapp\templates`

webtestappフォルダ作成。

`C:\Users\○○○\django\testproject\webtestapp\templates\webtestapp`

htmlファイルを作成。

`C:\Users\○○○\django\testproject\webtestapp\templates\webtestapp\index.html`

簡単な表示をさせてみます。

```testproject/webtestapp/templates/webtestapp/index.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>テストWebアプリ</title>
  </head>
  <body>
    <h1>index.html表示してます</h1>
  </body>
</html>
```
ただのHTMLですね。

## viewsとhtmlテンプレートで表示を作る

### views.py変更 htmlに表示させる内容
前回使っていた`HttpResponse`はテンプレートを出力（レンダー）するのには不要なので消してテンプレートを使うように変えましょう。


```testproject/webtestapp/views.py
from django.shortcuts import render

def index(request):
    return render(request,'webtestapp/index.html')
```

render関数の引数はrequestが第一引数。
第二引数はtemplatesフォルダからみてどこのファイルを参照するかです。

:::note info
testproject/webtestapp/templates/webtestapp/index.html
という構成にしました。
Djangoがデフォルトでtemplatesまではhtmlファイルを探してくれるのでそれ以降のフォルダを指定するので
'webtestapp/index.html' になります。
:::

### テンプレート使った表示の確認

```
python manage.py runserver
```

![キャプチャ.JPG](https://qiita-image-store.s3.amazonaws.com/0/260345/99176427-d86a-d667-d440-5eb57007f5a7.jpeg)


OKそうです。
ただ、HTMLを表示させただけですが、表示は確認できました。

### データをテンプレートに埋め込む

では、本題のデータを埋め込む方法を見ていきましょう

```testproject/webtestapp/templates/webtestapp/index.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>テストWebアプリ</title>
  </head>
  <body>
    <h1>index.html表示してます</h1>
    {{ insert_something }}
  </body>
</html>
```

変更箇所は`{{ insert_something }}`だけです。`insert_something`というデータをviewに用意しましょう。 
データは辞書で指定します。変数の名前は何でもいいですので今回は`my_dict`を引数に追加することにします。


```testproject/webtestapp/views.py
from django.shortcuts import render

def index(request):
    my_dict = {
        'insert_something':"views.pyのinsert_something部分です。",
    }
    return render(request, 'webtestapp/index.html', my_dict)
```

用意したデータを第三引数に指定。HTMLテンプレートの中で`insert_something`というデータを埋め込むと指定したので、対応するようにキー名`insert_something`を用意しました。


表示を確認してみましょう。

![キャプチャaa.JPG](https://qiita-image-store.s3.amazonaws.com/0/260345/051fe6c8-1f3c-1e4e-a2cb-599bbbb905ba.jpeg)


ちゃんと`mydict`の中の`insert_something`の中身である、
`views.pyのinsert_something部分です。`
という文字を表示できました。

#### 複数データを埋め込む
何個でも表示可能です。追加したいときは手順は同じように辞書とhtmlテンプレートファイルに追加します。

```testproject/webtestapp/views.py
from django.shortcuts import render

def index(request):
    my_dict = {
        'insert_something':"views.pyのinsert_something部分です。",
        'name':'Bashi',
    }
    return render(request, 'webtestapp/index.html', my_dict)
```

```testproject/webtestapp/templates/webtestapp/index.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>テストWebアプリ</title>
  </head>
  <body>
    <h1>index.html表示してます</h1>
    {{ insert_something }}
    <p>作成者は<b>{{ name }}</b>です。</p>
  </body>
</html>
```

![キャプチャsa.JPG](https://qiita-image-store.s3.amazonaws.com/0/260345/f8e36aa9-8e9e-2a56-3406-47650ca43f87.jpeg)

## テンプレートで for によりリストデータを表示させる
Pythonで使えるforと同じようなものをhtmlテンプレートでも使うことができます。
試しにテキトーなタイトルを表示させるため複数のデータ(リスト)を用意します。

```testproject/webtestapp/views.py
from django.shortcuts import render

def index(request):
    my_dict = {
        'insert_something':"views.pyのinsert_something部分です。",
        'name':'Bashi',
        'test_titles': ['title 1', 'title 2', 'title 3'],  # 追加
    }
    return render(request, 'webtestapp/index.html', my_dict)
```

テンプレートではデータを表示するため`for`を使います。

```testproject/webtestapp/templates/webtestapp/index.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>テストWebアプリ</title>
  </head>
  <body>
    <h1>index.html表示してます</h1>
    {{ insert_something }}
    <p>作成者は<b>{{ name }}</b>です。</p>
    <h2>タイトル表示</h2>
    <ul>
      {% for title in test_titles %}
        <li>{{ title }}</li>
      {% endfor %}
    </ul>
  </body>
</html>
```
表示した結果 ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/486c898d-41d1-e305-bc81-e49c9a1dc052.png)

Pythonの`for`と違うのは`endfor`と終わりを書くところですが、大体同じように使えます。

### テンプレートでの記法
`{% %}`と`{{ }}`というのが出てきて、間違いそうですが、以下のような違いがあります。

- `{{ }}`はデータをテンプレートの中に埋め込んでほしい(画面に表示したい)ときに使う
- `{% %}`は、何かしら計算・処理をしてほしい(※画面に出力するのではない)ときに使う

:::note warn
細かくは触れませんがテンプレートで使える for は似てるだけでPythonのforより性能悪く、機能制限されているのでガッツリ処理をするようなものには使わない方がいいです。
:::

## テンプレートで if を使い、表示させるデータに条件を付ける
試しに`test_titles`の`title 2`だけ表示するようにしてます。

```testproject/webtestapp/templates/webtestapp/index.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>テストWebアプリ</title>
  </head>
  <body>
    <h1>index.html表示してます</h1>
    {{ insert_something }}
    <p>作成者は<b>{{ name }}</b>です。</p>
    <h2>タイトル表示</h2>
    <ul>
      {% for title in test_titles %}
        {% if title == 'title 2'%}
          <li>{{ title }}</li>
        {% endif %}
      {% endfor %}
    </ul>
  </body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/97848789-4c4d-cc89-c171-b488ed8ed611.png)

### `elif`, `else`も使える

```testproject/webtestapp/templates/webtestapp/index.html
...
    <ul>
      {% for title in test_titles %}
        {% if title == 'title 2' %}
          <li>{{ title }}</li>
        {% elif title == 'title 3' %}
          <li>見せられないよ</li>
        {% else %}
          <li>xxxx</li>
        {% endif %}
      {% endfor %}
    </ul>
...
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/9e104ffe-d984-5881-79a5-4e1d8d1bf98f.png)

- `title 2`はifの条件なので普通に表示
- `title 3`はelifの条件なので「見せられないよ」
- `title 1`はif, elifの条件に当てはまらないので「xxxx」

が、表示されています。

## ついでに
※今回わざわざtemplatesフォルダの中にwebtestappフォルダを作ったのは、フォルダ分けできるというのを示したかったからです。
もしそんなにテンプレートの数が多くないというなら、webtestappを作る必要はなく、templatesフォルダ直下にindex.htmlをおいて、

`return render(request, 'index.html')`

でもOK。

# :pushpin: 一連の記事

|  | 内容|
|:----:|:----:|
|**part1**|[簡単な文字表示アプリを作る](https://qiita.com/Bashi50/items/c686d30fa4fdba4582ad)|
|**part2**|**HTMLテンプレート表示　← ココ**|
|**part3**|["画像" "CSS" "Javascript"実装](https://qiita.com/Bashi50/items/3452bd1692fdd0ac6392)|
|**part4**|[フォーム送信](https://qiita.com/Bashi50/items/93da7a071b2e02dc21ed)|
|**part5**|[データベースの値取得・更新](https://qiita.com/Bashi50/items/280bc341eeec5d7f8797)|
|**番外編**|[Django AWS デプロイ](https://qiita.com/Bashi50/items/d5bc47eeb9668304aaa2)|
|**APIサーバー編**|[Django REST frameworkとReact #4](https://qiita.com/Bashi50/items/203505440049d759b694)|


# 参考
この章のコードは以下です。確認やコピペでどうぞ

https://github.com/kohishibashi/easy-django/tree/part2