【Flask】 Jinja2 テンプレートでコンポーネントを効率的に分割する方法

  • jinja2

本記事では、Flask アプリケーションの Jinja2 テンプレートエンジンでのテンプレート分割の方法と、その利点について詳しく解説します。

Flask は Python で書かれた軽量なWebフレームワークであり、 Jinja2 はそのテンプレートエンジンとして広く利用されています。

Flask と Jinja2 の組み合わせは、シンプルで柔軟なアプリケーション開発を行う上で、よく採用されると思います。

Webアプリケーション開発において、コードの再利用性と保守性はかなり大事ですよね。

モダンなシステムではフロントエンドを React や Vue.js を用いて実装することが多いですが、軽量で小規模なアプリケーションでは、テンプレートエンジンを使った開発の方が生産性の面で優れている場合も多いです。

Flask フレームワークと Jinja2 テンプレートエンジンを使用する場合、テンプレートを分割してコンポーネント化することで、メンテナンスしやすいシステムにできます。

テンプレート分割の重要性について

テンプレートを小さなコンポーネントに分割することには多くのメリットがあります。

  • コードの再利用性の向上
  • メンテナンスの容易さ
  • チーム開発での作業効率の向上
  • アプリケーションの拡張性の向上

Sponsored

言うまでもないことかもしれませんが、上記の考慮をせずに、画面ごとに HTML を実装していると、後から修正が大変になります。

Jinja2 でのテンプレート分割方法

Jinja2 では、{% include %}{% extends %} の2つの主要な方法でテンプレートを分割できます。

1. includeを使用したコンポーネントの分割

{% include %} を使用すると、小さなコンポーネントを別のテンプレートファイルに分割し、必要な場所で再利用できます。

例えば、ナビゲーションバーのコンポーネントを作成する場合のコード例を紹介します。

navbar.html として実装するとします。

<!-- templates/components/navbar.html -->
<nav>
    <ul>
        <li><a href="{{ url_for('index') }}">ホーム</a></li>
        <li><a href="{{ url_for('about') }}">概要</a></li>
        <li><a href="{{ url_for('contact') }}">お問合せ</a></li>
    </ul>
</nav>

このコンポーネントを使用する実装は次のようになります。

<!-- templates/layout.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}タイトル{% endblock %}</title>
</head>
<body>
    {% include 'components/navbar.html' %}

    <main>
        {% block content %}
        {% endblock %}
    </main>

</body>
</html>

{% include 'components/navbar.html' %} の記述箇所が、コンポーネントを呼んでいる部分です。

このようにコンポーネント単位で分割しておけば、別の場所でも再利用できますね。

2. extendsを使用したレイアウトの継承

{% extends %} を使用すると、基本レイアウトを定義して、他のページでそれを拡張できます。

<!-- templates/page.html -->
{% extends 'layout.html' %}

{% block title %}タイトル{% endblock %}

{% block content %}
    <h1>コンテンツ</h1>
    <p>Hello World !!!</p>
{% endblock %}

例えば、先ほどの include の例で記載したような、 <!DOCTYPE html> から始めるような HTML 全体の記述は1箇所で済みます。

よくある構成として、共通スクリプトなどを含んだヘッダー、メニューなどを含んだナビゲーションバー、コンテンツエリア、フッターを定義したテンプレートを base.htmllayout.html として作成し、各画面で呼び出す形式を取ることが多いです。

Sponsored

動的コンポーネントの作成

コンポーネントに動的なデータを渡すこともできます。

例えば、再利用可能なカード形式のコンポーネントを以下のように定義しているとします。

&lt;!-- templates/components/card.html --&gt;
&lt;div class=&quot;card&quot;&gt;
    &lt;h2&gt;{{ title }}&lt;/h2&gt;
    &lt;p&gt;{{ content }}&lt;/p&gt;
    {% if button_text %}
        &lt;a href=&quot;{{ button_url }}&quot; class=&quot;button&quot;&gt;{{ button_text }}&lt;/a&gt;
    {% endif %}
&lt;/div&gt;

このコンポーネントは、タイトルやコンテンツ、ボタンのラベルやURLが未定義ですよね。

これを、 include で呼び出す際に、 with でパラメータを渡すことができます。

{% with title=&quot;新着情報&quot;, content=&quot;最新のニュースをチェック&quot;, button_text=&quot;詳細&quot;, button_url=url_for(&#039;news&#039;) %}
    {% include &#039;components/card.html&#039; %}
{% endwith %}

この方法であれば、小さなコンポーネントに分割して再利用できるので、コード量がかなり削減できるしメンテナンス性も上がります。

React を使うほどでもないプロジェクトの場合でも、このようにコンポーネント化は意識したいですね。

Flask でのセットアップ

せっかくなので、 Flask アプリケーションで Jinja2 テンプレートを使用するための基本的なセットアップのサンプルコードも紹介します。

from flask import Flask, render_template

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    return render_template(&#039;page.html&#039;)

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)

render_template で、画面を定義している HTML を呼び出すだけですね。

おわりに

Flask の場合は小規模な開発が多いかもしれませんが、それでも保守性の高いコードの意識は常にしたいものです。

/blogs/flask-jinja2-if-conditions/

if の書き方も(ちょっぴり)癖があるので、上記記事も参考にしてみてください。