◾️はじめに
Jinja2の繰り返し(ループ)についてメモ。
目次
【1】for文 【2】ループの制御文 1)break文 2)continue文 【3】loop 1)主なメソッド 2)サンプル 【4】使用上の注意:変数をループする場合の注意点 1)NG例 2)OK例
【1】for文
サンプル
{% for name in name_vals: %} <p>Hello, {{ name + " from USA" }}!!!</p> {% endfor %}
【2】ループの制御文
* if文と組み合わせて使える
1)break文
{% for item in items %} {% if item == 'TheEnd' %} {% break %} {# ! 注目 ! #} {% endif %} <li>{{ item }}</li> {% endfor %}
2)continue文
{% for item in items %} {% if item == 'TheSkip' %} {% continue %} {# ! 注目 ! #} {% endif %} <li>{{ item }}</li> {% endfor %}
【3】loop
* ループを制御するために用意されている loop が便利。
https://techblog.recochoku.jp/3422
1)主なメソッド
* 以下の公式ドキュメントに全てのメソッドが載っている
https://jinja.palletsprojects.com/en/3.0.x/templates/#for
Express | Explanations |
---|---|
loop.index | ループのインデックスを返す |
loop.first | 最初のループの場合 True, それ以外は False |
loop.last | 最後のループの場合 True, それ以外は False |
loop.length | ループの回数を返す |
2)サンプル
{# ループの最後は「,」は要らないので、それを制御する #} CREATE TABLE demo_table {% for column in columns %} {{ column }} TEXT{% "," if not loop.last else "" %} {# ! 注目 ! #} {% endfor %}
【4】使用上の注意:変数をループする場合の注意点
* 変数が文字列もしくは1要素のタプルの場合、文字列として扱い 1文字づつループされてしまう => タプルじゃなく、リストならOK
1)NG例
* 今回の例は、以下のようにするのだが、「出力結果(NG) 」をみて分かる通り 1文字づつループされてしまう(「table_names=['table1']」ならOK) + 1要素であれば、SELECT文のみ + 複数要素であれば、SELECT文+UNION ALLで繋ぐ
demo.py
from jinja2 import Environment, FileSystemLoader env = Environment(loader=FileSystemLoader('./', encoding='utf8')) template = env.get_template('./templates/sql.j2') result = template.render( #table_names = 'table1' # NG #table_names = ['table1'] # OK table_names = ('table1') # NG #table_names = ['table1', 'table2', 'table3'] # OK #table_names = ('table1', 'table2', 'table3') # OK ) print(result)
./templates/sql.j2
{%- for table in table_names %} SELECT COUNT(*) FROM {{ table }} {%- if not loop.last %} UNION ALL {%- endif %} {%- endfor %}
出力結果(NG)
SELECT COUNT(*) FROM t UNION ALL SELECT COUNT(*) FROM a UNION ALL SELECT COUNT(*) FROM b UNION ALL SELECT COUNT(*) FROM l UNION ALL SELECT COUNT(*) FROM e UNION ALL SELECT COUNT(*) FROM 1
2)OK例
* 変数の型チェックして対応する
./templates/sql.j2
{%- if table_names is iterable and table_names is not string and table_names is not mapping %} {%- for table in table_names %} SELECT COUNT(*) FROM {{ table }} {%- if not loop.last %} UNION ALL {%- endif %} {%- endfor %} {%- else %} SELECT COUNT(*) FROM {{ tabel_names }} {%- endif %}
出力結果(OK)
SELECT COUNT(*) FROM table1
関連記事
Jinja2 ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2024/10/19/000848
Jinja2 ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2024/10/18/001757
Jinja2 ~ フィルタ ~
https://dk521123.hatenablog.com/entry/2024/10/20/002622
Jinja2 ~ Macro ~
https://dk521123.hatenablog.com/entry/2023/11/28/235951
Jinja2 ~ 変数 ~
https://dk521123.hatenablog.com/entry/2025/04/05/131421
Jinja2 ~ 条件分岐 ~
https://dk521123.hatenablog.com/entry/2025/04/06/001255
Jinja2 ~ do文 ~
https://dk521123.hatenablog.com/entry/2025/04/03/221326
Jinja2 ~ Whitespace Control ~
https://dk521123.hatenablog.com/entry/2024/10/29/151203
dbt ~ 条件分岐 ~
https://dk521123.hatenablog.com/entry/2024/09/11/003301
Flask ~ jinja2 ~
https://dk521123.hatenablog.com/entry/2018/09/22/142348
標準テンプレートエンジン
https://dk521123.hatenablog.com/entry/2020/01/07/212138