この記事では、FlaskのテンプレートエンジンであるJinja2の使い方について、解説します。Jinja2はPythonのWebサービスでよく用いられるため、覚えておいて損はないです。
もしPythonのフレームワークであるDjangoを経験していれば、構文がよく似ているため、すんなりと理解することが出来ると思います。
スポンサーリンク
Jinja2とは
Jinja2は、Python用のテンプレートエンジンの1つ。Pythonの有名なフレームワークである、Djangoのテンプレートエンジンに構文がよく似ています。Jinja2は基本的にHTMLやXML生成に使われるが、どのような文書でも生成できます。(例えばソースコードやMarkdownなど)
Jinja2は、Flask内のテンプレートエンジンとして組み込まれています。そのため、Flaskの環境があれば、追加のインスール不要でJinja2が使えます。
ちなみにJinja2 は、 「じんじゃ(神社)」 と読むそうです。
はじめに
FlaskでJinja2を使用する場合は、Jinja2のテンプレートファイルを、templatesディレクトリに作成します。templates以外のフォルダにJinja2のテンプレートを作成しても、Flaskは認識してくれませんのでご注意を。
project_root
├── app.py
└── templates
├── index.html
└── about.html
Jinja2の基本的な使い方
ほほ公式のままですが、下記がJinja2のテンプレートのサンプルです。
<title>{{title}}</title>
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
テンプレート構文
Jinja2テンプレートの基本的な構文です。
構文 | 説明 |
---|---|
{% ... %} |
ステートメント |
{{ ... }} |
式 |
{# ... #} |
コメント |
# ... ## |
行ステートメント |
Jinja2にパラメータを渡す
render_template()
に名前付き引数を指定すると、Jinja2のテンプレートにパラメーターを渡すことができます。パラメータを渡す、いくつかのサンプルコードを紹介します。
文字列(str)を渡す
[Python]
from flask import render_template
@app.route("/index")
def index():
msg = 'Hello'
return render_template('index.html', msg = msg)
[Teamplate]
<div>
<p>{{message}}</p>
</div>
辞書(dict)を渡す
[Python]
from flask import render_template
@app.route("/index")
def index():
user = { 'name': '山田太郎', 'age': 20 }
return render_template('index.html', user = user)
[Teamplate]
<div>
<p>ユーザ名: {{user.name}}</p>
<p>年齢: {{user.age}}</p>
</div>
クラスを渡す
[Python]
from flask import render_template
@app.route("/index")
def index():
user = User()
user.name = '山田太郎'
user.age = 200
return render_template('index.html', user = user)
[Teamplate]
<div>
<p>ユーザ名: {{user.name}}</p>
<p>年齢: {{user.age}}</p>
</div>
Jinja2に複数のパラメータを渡すには
Jinja2のテンプレートに複数のパラメータを渡すには、Pythonのrender_template
関数呼び出し時に、名前付き引数を複数指定してやるだけです。
[Python]
from flask import render_template
@app.route("/index")
def index():
user = User()
user.name = '山田太郎'
user.age = 200
return render_template('index.html', msg = "Hello", user = user)
[Teamplate]
<p>{{msg}}</p>
<div>
<p>ユーザ名: {{user.name}}</p>
<p>年齢: {{user.age}}</p>
</div>
スポンサーリンク
Jinja2のテンプレートで分岐する(if)
if文は、Pythonの記法とほとんど同じです。Pythonとの違いとして、行末のコロン(:)が不要なことと、if文を終了するときは、{% endif %}
と書きます。
{% if user.age < 20 %}
<p>未成年</p>
{% elif user.age >= 20 and user.age <= 60 %}
<p>現役</p>
{% else %}
<p>シルバー</p>
{% endif %}
Jinja2のテンプレートで繰り返し(for)
<select>
{% for user in users %}
<option value="{{user.id}}" {{'selected' if user.id == sel_id else ''}}>{{user.name}}</option>
{% endfor %}
</select>
エスケープ(Jinja2の"{{", "{%"をエスケープ)
Jinja2テンプレートの特殊文字である"{{"や "{%“を、文字として扱いたい場合は、{% raw %}
ブロックを使用します。{% raw %}
ブロック内に書かれた内容は、すべて文字として扱われるため、”{{"や "{%"などの特殊文字を文字として表示させる事ができます。
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
Jinja2 のテンプレートを継承する
ヘッダーや、サイドメニューなど、どのページでも共通している部分を、共通のレイアウトとして作成しておき、そのレイアウトを継承させた、子テンプレートを作成できます。
継承を行なった子テンプレートは、共通部分のHTMLを記述する必要がなく、個別部分のHTMLだけを記述します。これにより、もし共通部分のレイアウトに手が入る場合、共通のレイアウトを1箇所修正するだけで済むため、保守性がよくなります。
[base.html]
<!DOCTYPE html>
<html lang="ja">
<head>
<title>{% block title %}{% endblock %} - サンプルサイト</title>
{% block head %}
<link rel="stylesheet" href="style.css" />
{% endblock %}
</head>
<body>
<!-- 共通ヘッダ -->
<header>
<h1>{% block title %}{% endblock %}</h1>
</header>
<!-- コンテンツ部分 -->
<div id="content">
{% block body %}
{% endblock %}
</div>
</body>
</html>
[子テンプレート]
{% extends "base.html" %}
{% block title %}ページタイトル{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.message { color: #f00; }
</style>
{% endblock %}
{% block content %}
<p class="message">
Welcome to my awesome homepage.
</p>
{% endblock %}
スポンサーリンク
Jinja2 のインクルード機能
Jinja2のインクルード(include)機能を使うと、継承を使うほどでもないけど、ページで共通している部分をコンポーネント化できます。例えば、ページングを行うページネーションなどをコンポーネント化しておくと、インクルード機能で複数の画面から使用できて便利です。
[pagger.html]
```html
<!--前のページ-->
{% if has_previous %}
<a href="mypage?page={{ previous_page }}">前</a>
{% endif %}
<!--ページ番号-->
<span>{{ page.number }} / {{ page.paginator.num_pages }}</span>
<!--次のページ-->
{% if has_next %}
<a href="mypage?page={{ next_page }}">次</a>
{% endif %}
上で作成したテンプレートはinclude
で読み込みます。
<nav>
<!--上で作成した部品を読み込む-->
{% include "pagger.html" %}
</nav>
0 件のコメント:
コメントを投稿