Flaskは、Webアプリケーションの構築を簡素化するために、Jinja2という強力なテンプレートエンジンを使用しています。Jinja2を使うことで、HTMLの静的な部分と動的な部分を分け、動的にコンテンツを生成することができます。
この記事では、FlaskのJinja2テンプレートエンジンを使い、動的にコンテンツをレンダリングする方法を学び、Webページのデザインを柔軟にする方法を紹介しています。
Jinja2とは?
Jinja2は、Python用のテンプレートエンジンで、Flaskのデフォルトのテンプレートエンジンとして使用されています。Jinja2は、PythonのコードをHTMLに埋め込んで動的なコンテンツを生成することができ、Webアプリケーションに柔軟性と効率性が出ます。
Jinja2の主な特徴:
- 動的コンテンツの生成: PythonのデータをHTMLに挿入できる
- 制御構造: ループや条件分岐が可能
- フィルターと変数: データの加工や変換を簡単に行える
- テンプレートの継承: ベースとなるHTML構造を共通化して再利用できる
FlaskでJinja2を使う方法
基本的な使い方
FlaskでJinja2を使用するためには、render_template()
関数を使います。この関数を使うことで、PythonのデータをHTMLテンプレートに渡して、動的なWebページを生成できます。
例: index.htmlテンプレートを使って動的コンテンツを表示
まず、Flaskアプリケーションのコードを以下のように作成します。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
# 渡すデータ
user_name = 'John'
return render_template('index.html', name=user_name)
if __name__ == '__main__':
app.run(debug=True)
HTMLテンプレートの作成
templates
というフォルダを作成し、その中にindex.html
というテンプレートファイルを作成します。Flaskは、render_template()
を呼び出すことで、templates
フォルダ内のHTMLファイルをレンダリングします。
index.htmlの内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>
このHTMLでは、{{ name }}
という部分がJinja2のテンプレートタグです。この部分には、Flaskから渡されたname
という変数が挿入されます。
結果

この状態でFlaskアプリケーションを実行し、ブラウザでhttp://127.0.0.1:5000/
にアクセスすると、ページには「Hello, John!」と表示されます。Flaskがrender_template()
を使って、name
変数をindex.html
に渡し、その値を表示しています。
Jinja2の制御構造
Jinja2は、条件分岐やループなど、様々な制御構造があります。これにより、動的なWebページをより柔軟に作成できます。
条件分岐 (if文)
Jinja2では、{% if condition %}...{% endif %}
を使って条件分岐を行うことができます。
例: ユーザーのログイン状態を表示
@app.route('/')
def home():
logged_in = True
return render_template('index.html', logged_in=logged_in)
index.htmlで条件分岐を使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome</title>
</head>
<body>
{% if logged_in %}
<h1>Welcome, User!</h1>
{% else %}
<h1>Please log in.</h1>
{% endif %}
</body>
</html>
この例では、logged_in
がTrue
の場合、「Welcome, User!」と表示され、False
の場合は「Please log in.」と表示されます。
結果

ループ (for文)
Jinja2では、{% for item in collection %}...{% endfor %}
を使ってリストや辞書をループ処理できます。
例: リストのアイテムを表示
@app.route('/')
def home():
items = ['Apple', 'Banana', 'Cherry']
return render_template('index.html', items=items)
index.htmlでループを使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Items</title>
</head>
<body>
<h1>Items List:</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>
この例では、items
リストの各要素が<li>
タグとして表示されます。
結果

Jinja2のフィルターと変数の操作
Jinja2では、データを表示する際にフィルターを使って加工することができます。
フィルターの使用
例えば、文字列を大文字に変換したり、日付をフォーマットしたりすることができます。
例: 文字列を大文字に変換
@app.route('/')
def home():
message = 'hello, world'
return render_template('index.html', message=message)
index.htmlでフィルターを使う
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Message</title>
</head>
<body>
<h1>{{ message|upper }}</h1> <!-- upperフィルターを使って大文字に -->
</body>
</html>
この場合、message
はupper
フィルターによって大文字に変換され、HELLO, WORLD
と表示されます。
結果

テンプレートの継承
Jinja2では、テンプレートの継承を使って、共通のレイアウトを作成し、異なる部分だけを動的に変更することができます。これにより、コードの重複を避け、メンテナンス性を向上させることができます。
以下では、Flaskのアプリケーションを作成し、base.html
という共通のベーステンプレートを作成し、そのテンプレートをhome.html
という個別のページで継承して使用します。
Flaskアプリケーション(Pythonプログラム)
まず、Flaskアプリケーションを作成します。このアプリケーションでは、home
というURLにアクセスすると、home.html
がレンダリングされるようにします。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
if __name__ == '__main__':
app.run(debug=True)
ベーステンプレートを作成
次に、すべてのページで共通するHTMLのレイアウト(ヘッダー、フッターなど)を定義したbase.html
テンプレートを作成します。このテンプレートは、他のページで継承されて、内容が動的に変更されます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
<header>
<h1>Welcome to My Website</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<div>
{% block content %}{% endblock %}
</div>
<footer>
<p>© 2023 My Website</p>
</footer>
</body>
</html>
継承を使ったページ作成
次に、home.html
というページでベーステンプレートを継承します。
{% extends 'base.html' %}
{% block title %}Home Page{% endblock %}
{% block content %}
<h2>This is the home page</h2>
<p>Welcome to my website!</p>
{% endblock %}
これにより、home.html
はbase.html
のレイアウトを継承し、title
とcontent
だけを動的に変更しています。
結果

次にaboutページを作成してみます。ここでもbase.html
のレイアウトを継承します。
Flaskアプリケーションに/aboutルートを追加する
app.py
に/about
ルートを追加します。これにより、/about
にアクセスしたときに表示されるコンテンツを定義することができます。
Flaskアプリケーションに/about
ルートを追加
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
# /aboutルートを追加
@app.route('/about')
def about():
return render_template('about.html')
if __name__ == '__main__':
app.run(debug=True)
about.htmlテンプレートを作成する
/about
ルートにアクセスしたときに表示するHTMLテンプレート(about.html
)を作成します。templates
フォルダ内に新しいabout.html
ファイルを作成し、必要なコンテンツを追加します。
templates/about.html
の内容:
{% extends 'base.html' %}
{% block title %}About Page{% endblock %}
{% block content %}
<h2>About Us</h2>
<p>Welcome to the About page of our website. Here you can learn more about our mission and goals.</p>
{% endblock %}
ディレクトリ構成
プロジェクトのディレクトリ構成は次のようになります:
/your-flask-app
/templates
base.html
home.html
about.html <-- 新たに追加したabout.html
app.py
Flaskアプリケーションを再起動
app.py
に変更を加えた後、Flaskサーバーを再起動して新しいルートが反映されるようにします。
python app.py
結果

まとめ
Jinja2は、FlaskでのWeb開発をより柔軟に、効率的にするために便利です。テンプレートエンジンを使うことで、HTMLを動的に生成し、データを埋め込んで表示することができます。また、制御構造やフィルターを使うことで、さらに高度な処理も可能になります。テンプレートの継承を使えば、共通のレイアウトを再利用し、コードの重複を減らすことができます。
これでFlaskとJinja2を使ったWebアプリケーションの開発がよりスムーズに進められるようになります!