jinja2 を用いてHTMLファイルを作成 [Pythonチートシート]

Python

Pythonを使っていると複数のコードで共通して使用しているコードがあることに気付きます。その作業を完全に覚えていればいいのですが毎回ウェブで調べてコードを記述して、とすると目的の作業は同じなのにシートごとにコード記述方法が違ってしまい見にくくなってしまいます。
そんなことを解消するのがPythonチートシートです。
今回は「 jinja2 を用いてHTMLファイルを作成 」するコードを紹介します。

環境設定
◆ Mac OS
◆ Python 3
◆ JupyterLab

想定する利用シーン

Pythonで作成した変数やlistの値をHTMLの一部に挿入したいなぁ

 

HTMLで複数箇所に同じテキストを一度に入れたりテンプレート化したいな

そんな時はJinja2を用いればできれば解決できますよ

Jinja2 とは

Jinja2とは、「python用のhtml作成時に使用できるテンプレートエンジン」です。

Jinja is a fast, expressive, extensible templating engine. Special placeholders in the template allow writing code similar to Python syntax. Then the template is passed data to render the final document.

引用:Jinja2 HP

前準備 フォルダの作成

このコードの実行によりファイル名を読み込むフォルダ・ファイルはこのJupyterLabで作成した「.ipynb」ファイルとの相対パスで場所を示します。

今「.ipynb」を保存しているフォルダと同じ階層に「templates」と「results」というフォルダを作成してください。

任意のフォルダ
- .ipynb (本ファイル)
- templates (フォルダ)
- results (フォルダ)

各コードの紹介時に使用するテキストファイルを示しますが、それらは作成した「templates」フォルダの中に保存してください

 

Jinja2のインストールと動作確認

それでは実際にコードを紹介します。

# Jinja2のインストール
!pip install jinja2

# 基本的なJinja2の実行
from jinja2 import Template
 
tpl_text = '私の名前は{{ name }}で、年齢は{{ age }}です'
template = Template(tpl_text)
 
data = {'name': 'Mark', 'age': '30'}
disp_text = template.render(data) # 辞書で指定する
print(disp_text) # 実行結果:私の名前はMarkで、年齢は30です

# 実行結果
# > 私の名前はMarkで、年齢は30です

Jinjaでは {{ … }} : Expressions を用いてテンプレート (template)となるテキストを作成し (7行目)、そのテンプレート中の {{ … }} : Expressionsに入れ込むパラメータ (parameter) を指定します (10行目)。その後テンプレートとパラメータをrenderingする(11行目)ことで、実行結果に示すようにテンプレート中にパラメータの文字列・値を入れることができます。

テンプレート中の {{ … }} : Expressionsは以下のようにPythonの記述通り四則演算すること

# 四則演算
from jinja2 import Template
 
tpl_text = '私の名前は{{ name }}で、年齢は{{ age + 7 }} です'
template = Template(tpl_text)
 
data = {'name': 'Mark', 'age': 30}
disp_text = template.render(data) # 辞書で指定する
print(disp_text) # 実行結果:私の名前はMarkで、年齢は30です

# 実行結果
#> 私の名前はMarkで、年齢は37 です

 

上記の例はシンプルなテキストだったので一つのコード中に全て記載しましたが、一般的にjinjaを使用する際には、以下の3ファイルに構成を分けることが主流です。

  • template (htmlのテンプレート)
  • parameter (テンプレート中に挿入したいパラメータ)
  • rendering (jinjaを実行)

 

Jinja2の基本 (ファイル準備)

それでは、実際の運用に即した形式でJinja2の使用方法を見ていきます。まずはじめに以下の3ファイルを準備します。

  • template (htmlのテンプレート)
  • parameter (テンプレート中に挿入したいパラメータ)
  • rendering (jinjaを実行)

 

templateファイルの準備

本実行ファイルと同じディレクトリに作成した[templates]というフォルダに[sample_01.txt]というtxtファイルを作成し、以下のテンプレートの記載をします。

<h2> jinja2のテスト </h2> 
これは jinja2のテストです。
私の名前は {{ name }}で、年齢は {{ age }}です。

 

parameterファイルの作成

parameterファイルはjsonファイルで用意します。以下のコードを実行することで、「str」で定義したjsonファイルが「template」フォルダ中に作成されます。

import json

str = {
    'name' : 'Mark',
    'age' : 30
}

with open('./templates/parameter_01.json', 'w') as f:
    json.dump(str, f, ensure_ascii=False)

 

renderコードの作成

ここまでで作成した[templateファイル]と[parameterファイル]を読み込んでjinjaでrendering、ここではhtmlテンプレート中にパラメータで設定した情報を入れ込むことをしていきます。templateファイルを読み込むために必要なjinjaの機能としてEnvironmentがあり、以下のように記載します。

env = Environment(loader=FileSystemLoader('テンプレートファイル配置ディレクトリのルート'))

template = env.get_template(‘テンプレートファイル名’)

from jinja2 import Template, Environment, FileSystemLoader
import json

#テンプレート読み込み
env = Environment(loader=FileSystemLoader('./templates', encoding='utf8'))
template = env.get_template('sample_01.txt')

#パラメータファイル読み込み
with open('./templates/parameter_01.json') as f:
    parameters = json.load(f)

#レンダリングして出力
rendered = template.render(parameters)
print(rendered)

#レンダリングしてhtml出力
rendered_html = template.render(parameters)
with open('./results/result_01.html', 'w') as f:
    f.write(rendered_html)

 

実行結果

作成した「results」フォルダ中に「result_01.html」が作成されて、Jinja2のインストールと動作確認時と同じHTML文が出力されました。

 

Jinja2 {% … %} Statementsの利用

jinjaではテンプレート中に{% ... %}:Statementsを入れ、{{ ... }}:Expressionsと組み合わせることでhtml中でもpythonのようにfor文やif文処理を行うことができます。

以下に各コードごとの処理について解説していいきます。

for文

ここでは、複数のlist状になっている項目をfor文で繰り返し、文章形式とテーブル形式で表示させるようにします。 前準備として以下の[templateファイル]と[parameterファイル]を作成します。

 

templateファイルの準備

本実行ファイルと同じディレクトリに作成した[templates]というフォルダに[sample_02_for loop.txt]というtxtファイルを作成し、以下のテンプレートの記載をします。

なお {# … #}中の記載はコメントアウトされてJinja2のrendering時には現れません。

for文の作成には、{% for (変数) in (Expression) %} の形で記載します。Pythonの時のように「: (コロン)」は不要なので気を付けましょう。 またfor文 Statementsの終わりを示す際には{% endfor %} が必要なため忘れないようにしましょう。

{# for文のsample #}
<html>
    <body>
        <h2>jinjaとfor文</h2>
        商品と値段一覧
        {% for item in data_list %}
            <p>{{ item.name }}は{{ item.price }}です。</p>
        {% endfor %}


        <h2>table形式</h2>
        <table border=1>
            <tr>
              <th>商品</th>
              <th>値段</th>
              <th>店名</th>
            </tr>
            {% for item in data_list %}
                <tr>
                <td>{{ item.name | e}}</td>
                <td>{{ item.price | e}}</td>
                <td>{{ item.store | e}}</td>
                </tr>
            {% endfor %}
        </table>
    </body>
</html>

 

parameterファイルの作成

parameterファイルはjsonファイルで用意します。以下のコードを実行することで、「data」で定義したjsonファイルが「template」フォルダ中に作成されます。

data = {
    'data_list' : [
        { 
            'name': 'リンゴ',
            'price' : 150,
            'store' : 'A-mart'
        },
        { 
            'name': 'バナナ',
            'price' : 100,
            'store' : 'Super-B'
        }
    ]
}

with open('./jinja2/templates/parameter_02.json', 'w') as f:
    json.dump(data, f, ensure_ascii=False)

 

renderコードの作成

ここまでで作成した[templateファイル]と[parameterファイル]を読み込んでjinja2でrenderingします。

from jinja2 import Template, Environment, FileSystemLoader
import json

#テンプレート読み込み
env = Environment(loader=FileSystemLoader('./templates', encoding='utf8'))
template = env.get_template('sample_02_for loop.txt')

#パラメータファイル読み込み
with open('./templates/parameter_02.json') as f:
    parameters = json.load(f)

#レンダリングして出力
rendered = template.render(parameters)
print(rendered)

#レンダリングしてhtml出力
rendered_html = template.render(parameters)
with open('./results/result_02.html', 'w') as f:
    f.write(rendered_html)

 

実行結果

作成した「results」フォルダ中に「result_02.html」が作成されて、以下のHTML文が出力されました。

<html>
    <body>
        <h2>jinjaとfor文</h2>
        商品と値段一覧
        
            <p>リンゴは150です。</p>
        
            <p>バナナは100です。</p>
        


        <h2>table形式</h2>
        <table border=1>
            <tr>
              <th>商品</th>
              <th>値段</th>
              <th>店名</th>
            </tr>
            
                <tr>
                <td>リンゴ</td>
                <td>150</td>
                <td>A-mart</td>
                </tr>
            
                <tr>
                <td>バナナ</td>
                <td>100</td>
                <td>Super-B</td>
                </tr>
            
        </table>
    </body>
</html>

 

if文

ここでは取得したパラメータの値がプラスかマイナスかの結果に応じて、html中の文字の色を変更させるif文を作成します。

 

templateファイルの準備

本実行ファイルと同じディレクトリに作成した[templates]というフォルダに[sample_03_if_change color.txt]というtxtファイルを作成し、以下のテンプレートの記載をします。

if文の作成には、{% if …(Expression & 条件) %} の形で記載します。Pythonの時のように「: (コロン)」は不要なので気を付けましょう。 条件分岐の「elif」「else」はPythonと同様の使用方法です。またif文 Statementsの終わりを示す際には{% endif %} が必要なため忘れないようにしましょう。

{# if文のsample, 数値がプラスで緑色、マイナスで赤色 #}


<html>
    <body>
        <h2>jinjaとif文</h2>
        <p>色の凡例</p>
        <p><span style="color: #008000;">緑色(プラス)</span></p>
        <p><span style="color: #ff0000;">赤色(マイナス)</span></p>
        
        {% for item in data_list %}
            {% if item.profit > 0 %}
                <p><span style="color: #008000;">{{ item.profit }}でプラスです。</span></p>
            {% elif item.profit == 0 %}
                <p>{{ item.profit }}でプラスマイナス0です。</p>
            {% else %}
                <p><span style="color: #ff0000;">{{ item.profit }}でマイナスです。</span></p>
            {% endif %}
        {% endfor %}
        
        
    </body>
</html>

ここでは次のparameterファイルで設定する「profit」の数値がプラスであれば緑色マイナスであれば赤色で修飾し、±0であれば黒字のままとします。

 

parameterファイルの作成

parameterファイルはjsonファイルで用意します。以下のコードを実行することで、「data」で定義したjsonファイルが「template」フォルダ中に作成されます。

data = {
    'data_list' : [
        { 
            'name': 'リンゴ',
            'price' : 150,
            'profit' : 1000
        },
        { 
            'name': 'バナナ',
            'price' : 100,
            'profit' : -500
        },
        { 
            'name': 'レモン',
            'price' : 200,
            'profit' : 0
        }
    ]
}

with open('./jinja2/templates/parameter_03.json', 'w') as f:
    json.dump(data, f, ensure_ascii=False)

 

renderコード

from jinja2 import Template, Environment, FileSystemLoader
import json

#テンプレート読み込み
env = Environment(loader=FileSystemLoader('./templates', encoding='utf8'))
template = env.get_template('sample_03_if_change color.txt')

#パラメータファイル読み込み
with open('./templates/parameter_03.json') as f:
    parameters = json.load(f)

#レンダリングして出力
rendered = template.render(parameters)
print(rendered)

#レンダリングしてhtml出力
rendered_html = template.render(parameters)
with open('./results/result_03.html', 'w') as f:
    f.write(rendered_html)

 

実行結果

<html>
    <body>
        <h2>jinjaとif文</h2>
        <p>色の凡例</p>
        <p><span style="color: #008000;">緑色(プラス)</span></p>
        <p><span style="color: #ff0000;">赤色(マイナス)</span></p>

                <p><span style="color: #008000;">1000でプラスです。</span></p>        
                <p><span style="color: #ff0000;">-500でマイナスです。</span></p>                    
                <p>0でプラスマイナス0です。</p>
            
    </body>
</html>

 

最後に

jinja2を使用することでPythonとHTMLの連携が可能となり、これを活用することでPythonを用いたWordpressへの自動投稿を高い自由度で行えるようになりました。複雑な記事の作成のためには、テンプレート中の{% ... %}:Statementsを入れ、{{ ... }}:Expressionsの記載と、parameterをどう作成するかが鍵となると考えます。

Pythonチートシートで毎回よく使う作業のPythonコードをまとめ、今回は「jinja2 を用いてHTMLファイルを作成」するコードを紹介しました。

他にもいろいろなチートシートを用意しておりますので以下から確認してみてください。

普段よく使う作業の[ Pythonチートシート ]
Pythonを使っていると複数のコードで共通して使用しているコードがあることに気付きます。その作業を完全に覚えていればいいのですが毎回ウェブで調べてコードを記述して、とすると目的の作業は同じなのにシートごとにコード記述方法が違ってしまい見に...

コメント

タイトルとURLをコピーしました