pythonのためのテンプレートエンジン「Jinja2」便利な機能

pythonでwebサービスを作成すると利用されるのは、**Jinja**が多いと思います。

そんなJinjaには、たくさんの便利な機能があります。そんなJinjaをインストールから実装まで、*絶対やってほしい設定*を交えつつ、紹介していきます。

## 目次
- Jinjaの準備
- サンプルアプリを実装
- Jinjaの便利機能を紹介
    - パラメータを表示
    - for文
    - if文
    - ランダムに値を選択
- つまったところ
- おまけ

## 対象
- pythonのwebサービスでビューを楽に書きたい人
- Flaskでアプリケーションを作っている人
- pythonでwebサービスを作ろうとしている人

## Jinja2の準備
早速、準備をしていきましょう。

### Jinja2をインストール
他のライブラリと同じく`pip install`でインストールできます。

```bash

$ pip install Jinja2
```

### 【重要】PycharmでTemplate Languageの設定
Pycharm Professionalをお使いの方は絶対にこの設定をしてください。これをやらないと2分で頭がハゲます。
Pycharm Community Editionをお使いの方は、ハゲたらProfessionalを買ってくださいヽ(•̀ω•́ )ゝ。

#### 「⌘」 + 「,」でpreferencesを出現させて、検索フォームに「template」と入力
![image.png](https://qiita-image-store.s3.amazonaws.com/0/185039/17c34243-6dce-edee-28fd-693bfdf1ec85.png)

#### 「Jinja2」を選択して、適用
このgif通りやればできます！できなかったら [筆者のTwitterアカウント](https://twitter.com/kota_matchan)に連絡ださい。みなさんがハゲる前に対応します。

![](https://i.gyazo.com/7f03c8862dbd094313907f7f5a34e8d7.gif)

#### templatesディレクトリを「Template Folder」に変更
この設定をしておく、補完が効いてくれて、ビューをスイスイ書けます。
![](https://i.gyazo.com/b24c62fbc1c7ab93d5f3a4cd309b3d08.gif)

## サンプルアプリを実装
作ってなんぼ！ってことで簡単に書いていきましょう！

### ディレクトリ構成
こんな感じ！エラーに出くわすといけないので、とりあえず、同じ構成にしてください。

※ ディレクトリ名やファイル名は正確に真似してください。
※ app.pyとtemplates/は、同一階層です。

```
├── app.py
└── templates
    └── index.html
```

### ビューを実装
早速、Jinjaの記法を使って、ビューを書きます。この時点では、書き方がわからないかもしれませんが、それぞれの機能については、下で解説します。

```html:templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>サンプル</title>
</head>
<body>

<h2>自己紹介</h2>

<h3>{{ username }}</h3>

<h4>誕生日: {{ birth_day.year }}年{{ birth_day.month }}月{{ birth_day.day }}</h4>
{% if birth_day.month == 12 %}
    <p>今月、誕生日です！</p>
{% elif birth_day.month == 11 %}
    <p>先月、誕生日でした。</p>
{% endif %}

<h3>好きな女性タレント</h3>
<ul>
    {% for actress in actresses %}
        <li>{{ actress }}さん</li>
    {% endfor %}
</ul>


<div>2018年のM-1で、一番おもしろかったのは、
    <p style="font-size:18px; color: midnightblue">{{ comedians | random }}</p>だと思います。
</div>

</body>
</html>
```

### コントローラーを実装
この記事内では、コントローラーは主題ではないので深くは触れません。さらに、Jinja2での機能紹介を優先して、煩雑にもなってしまっています。

```python:app.py
from flask import Flask, render_template

app = Flask(__name__)
app.config["SECRET_KEY"] = "sample1204"


@app.route("/", methods=["GET"])
def index():
    username = "Kota"
    birth_day = {"year": 2000, "month": 11, "day": 25}
    actresses = ["有村架純", "中条あやみ", "石原さとみ"]
    comedians = ["和牛", "ジャルジャル", "霜降り明星"]

    return render_template("index.html",
                           username=username, birth_day=birth_day,
                           actresses=actresses, comedians=comedians)


if __name__ == "__main__":
    app.run()
```

後は、`app.py`を動かすだけ(๑•̀ㅂ•́)و✧

```bash
$ python app.py
```

## Jinja2の便利機能を紹介
上で書いた、`templates/index.html`を見ながら、説明します。

### パラメータを表示
flaskから渡した変数をそのまま表示するには、`{{`と`}}`で囲むだけ！

```html:templates/index.html
{{ username }}
```

### if文
pythonの文法とほとんど同じで書けます。
両脇に`{%`と`%}`が追加される程度です。
if文の終了を明示的にするために、`{% endif %}`と書きます。

```html:templates/index.html
{% if birth_day.month == 12 %}
    <p>今月、誕生日です！</p>
{% elif birth_day.month == 11 %}
    <p>先月、誕生日でした。</p>
{% endif %}
```

### for文
ビューでfor文を使えるテンプレートエンジンはたくさんあると思います。もちろんJinja2でも使えます。
pythonの文法と似ていますね。
これもfor文同様に`{%`と`%}`で囲み、`{% endfor %}`でfor文の終了をお知らせすれば、完成です。

```html:templates/index.html
<ul>
    {% for actress in actresses %}
        <li>{{ actress }}さん</li>
    {% endfor %}
</ul>
```

### ランダムに値を選択
ビューでは馴染み薄いかもしれませんが、*random*も使えます。
flaskから配列を渡すことも可能ですし、ビューで定義することも可能です。

```html:templates/index.html
<p style="font-size:18px; color: midnightblue">{{ comedians | random }}</p>

{# こうやっても書ける #}
{# <p style="font-size:18px; color: midnightblue">{{ ["和牛", "ジャルジャル", "霜降り明星"] | random }}</p> #}
```

(個人的にはここ3年ずっと和牛を応援しています。)

## つまったところ
### htmlファイルを作ったのに、エラーになる
よく見るのが、`jinja2.exceptions.TemplateNotFound: index.html`のエラー。

原因:
Jinja2が求めるディレクトリ構成になっていないから。

上にも書きましたが、ディレクトリ構成はこんな感じ！

```
├── app.py
└── templates
    └── index.html
```

- htmlファイルを格納しているディレクトリの名前は、`templates`にする
    - 複数形であることに注意
    - `templates`の下に更にディレクリを作って、その下にhtmlファイルを置くのは問題なし
- `app.py`と`templates`は同一階層にする

## おまけ
最後までお付き合いいただき、ありがとうございました。
少しでもお役に立てたのであれば、嬉しいです。

他にも便利機能はたくさんあるので、[Renttleのあれこれ ~はじめて0からサービスを開発~ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/renttle)が終わる前に書きたいと思います(ง `ω´)۶

[Jinja2の公式サイト](http://jinja.pocoo.org/)を見ると、鳥居が描かれています。なので、「Jinja」の語源は「神社」ということで良さそうです。
ただ、なんで神社に影響されたのかまでは、調査できなかったです_(┐「ε:)_ｽﾞｺｰ。

[Renttle](https://renttle.jp)というサービスを開発中です。ぜひ、使ってみて、レビューをください。

### P.S.
今までのアドベントカレンダーの記事を見てくれている方から、顔文字のセンスがおっさんっぽいとのレビューを頂いたので、[こちら](https://matome.naver.jp/odai/2135442470570037201)を参考に顔文字を採用しました。