見出し画像

Jinja2基礎


Jinja2とは

Pythonのテンプレートエンジンであり、主にWebアプリケーションや静的サイトジェネレーターなどで使用されています。
Flaskを使ってWebアプリケーションを開発する際、Jinja2テンプレートを使用してHTMLの生成を簡単に行うことができます。Jinja2テンプレートは、HTMLファイルにPythonの変数や制御構文(if文やforループなど)を埋め込むことができ、これにより動的なWebページを効率的に生成できます。

Jinja2の便利な機能(ChatGPT引用)

  1. 変数の置換: Jinja2テンプレートでは、{{ variable }}の形式を使用してPythonから渡された変数の値を挿入できます。これにより、動的なコンテンツの生成が容易になります。

  2. 制御構造:

    • 条件分岐: {% if %}{% elif %}{% else %}ステートメントを使って、条件に基づいて異なるコンテンツを表示できます。

    • ループ: {% for %}ループを使って、リストや辞書などのコレクションを繰り返し処理できます。

  3. 継承: Jinja2テンプレートでは、{% extends "base.html" %}の形式でベーステンプレートを継承し、{% block %}を使用してベーステンプレートの特定のセクションをオーバーライドすることができます。これにより、コードの再利用と整理が促進されます。

  4. マクロ: マクロを使って、テンプレート内で再利用可能な関数を定義できます。これは、繰り返し使用されるHTML構造を一箇所にまとめ、必要に応じて呼び出すことができるため便利です。

  5. フィルタ: 変数を表示する前に加工するためのフィルタが豊富に用意されています。例えば、{{ name|capitalize }}で変数nameの最初の文字を大文字にすることができます。

  6. テンプレートのインクルード: {% include 'header.html' %}のようにして、他のテンプレートファイルを現在のテンプレートファイルに挿入することができます。これにより、ページの特定の部分を別のファイルに分割して管理することができます。

  7. カスタムフィルタやグローバル関数の定義: Jinja2では、独自のフィルタや関数を定義し、テンプレート内で使用することができます。これにより、テンプレートの機能を拡張することが可能になります。

環境構築

Flaskを用います。Jinja2はFlaskのテンプレートエンジンとして組み込まれています。

ファイル構成

jinja2app.py
│
└─templates
        index.html

app.pyファイル

from flask import Flask, render_template

# 1 Flaskアプリケーションの設定
app = Flask(__name__)

@app.route("/")
def top():
    user_name = "kuwaharu"   # HTMLファイルで使う変数の設定 
    return render_template("index.html", name=user_name)

if __name__ == '__main__':
    app.run(debug=True)

変数の表示

{{ 変数名 }}で変数の表示ができます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jinja2</title>
</head>
<body>
    <p>{{ name }}さん、こんにちは</p>
</body>
</html>

変数の定義

{% 変数名 =  値 %}

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jinja2</title>
</head>
<body>
    {% set greeting = name + "さん、こんばんは" %}
    <p>{{ greeting }}</p>
</body>
</html>

with文

特定の変数を一時的にスコープに追加するための機能

{% with 変数名 = 値 %}
    <!-- ここで変数を使用 -->
{% endwith %}

制御構文

{% 制御構文 %}

if文

# app.py
from flask import Flask, render_template

# 1 Flaskアプリケーションの設定
app = Flask(__name__)

@app.route("/")
def top():
    user_name = "kuwaharu"
    now_time = 12
    return render_template("index.html", name=user_name, time = now_time)

if __name__ == '__main__':
    app.run(debug=True)
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jinja2</title>
</head>
<body>
    <p>{{ name }}さん、
        {% if 6 <= time < 11 %}
            おはようございます
        {% elif 11 <= time < 18 %}
            こんにちは
        {% else %}
            こんばんは
        {% endif %}
    </p>
</body>
</html>

for文

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jinja2</title>
</head>
<body>
    {% for i in range(10) %}
        <p>{{ i }}</p>
    {% endfor %}
</body>
</html>

継承

Pythonでいうクラスみたいなものです。

継承の利点

  • 再利用性: 共通のレイアウトやコンポーネントを複数のページで再利用できます。

  • 保守性: ヘッダー、フッターなどの共通要素を変更する場合、ベーステンプレートのみを編集するだけで済みます。

  • 整理性: ページの構造が明確になり、テンプレートの読みやすさと管理が向上します。


継承を使用してフッターとヘッダーは同じページを二つ作成します。

Pythonファイル(app.py)

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/base")
def base():
    return render_template("base.html")

@app.route("/child")
def child():
    return render_template("child.html")

if __name__ == '__main__':
    app.run(debug=True)

親ページ(base.html)

※cssはChatGPTが作成

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}マイウェブサイト{% endblock %}</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        header {
            background-color: #333;
            color: #fff;
            padding: 20px;
            text-align: center;
        }
        nav ul {
            list-style-type: none;
            padding: 0;
        }
        nav ul li {
            display: inline;
            margin: 0 10px;
        }
        nav ul li a {
            color: #fff;
            text-decoration: none;
        }
        main {
            padding: 20px;
        }
        footer {
            background-color: #333;
            color: #fff;
            text-align: center;
            padding: 10px;
            position: fixed;
            bottom: 0;
            width: 100%;
        }
    </style>
</head>
<body>
    <header>
        <h1>ウェブサイトのヘッダー</h1>
        <nav>
            <ul>
                <li><a href="/">ホーム</a></li>
                <li><a href="/about">私たちについて</a></li>
                <li><a href="/contact">お問い合わせ</a></li>
            </ul>
        </nav>
    </header>

    <main>
        {% block content %}
            <h2>親ページのコンテンツ</h2>
            <p>ここに親ページのコンテンツが入ります。</p>
        {% endblock %}
    </main>

    <footer>
        <p>&copy; 2024 マイウェブサイト</p>
    </footer>
</body>
</html>

子ページ(child.html)

{% extends "base.html" %}

{% block title %}子ページのタイトル{% endblock %}

{% block content %}
    <h2>子ページのコンテンツ</h2>
    <p>ここに子ページのコンテンツが入ります。</p>
{% endblock %}

継承の仕方

{% extends "親ファイル名" %}

ブロック宣言

ブロック宣言を使うことで、テンプレートの特定の部分を「ブロック」として定義し、これらのブロックを他のテンプレートからオーバーライド(上書き)できるようになります。先ほどの例だと{% block title %}や{% block content %}などです。

{% block ブロック名 %}
...
{% endblock %}

ブロック名は任意ですが、親ページと子ページで一致している必要があります。

マクロ

マクロは再利用可能なコードブロックを定義するための機能です。HTML内で関数を定義するイメージです。

マクロ定義

{% macro マクロ名(引数) %}
...
{% endmacro %}

マクロの呼び出し

{{ マクロ名(引数) }}

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jinja2</title>
</head>
<body>
    {% macro hello(name) %}
        <p>こんにちは、{{ name }}さん</p>
    {% endmacro %}

    {{ hello("kuwaharu") }}
    {{ hello("note") }}
    {{ hello("flask") }}
    {{ hello("Jinja2") }}
</body>
</html>


いいなと思ったら応援しよう!