最初の頃はbottleの話をよく書いてましたが最近は疎かになってましたので久しぶりです。今回はtemplate engineについてまとめておきます。
テンプレートエンジン(template engine)
WEBアプリケーションのUIは当然HTMLで作成しますが、生のHTMLは固定された内容しか表現できません。しかし、WEBアプリケーションでは、複数ある商品の繰り返しを表示したりログインしているユーザ名を表示したりと、動的に変わる部分を表現できなければいけません。
もちろん以下のようにPythonのコードで動的に文字列としてHTMLを組み上げることで動的なHTMLを作成することは可能です。
@get('/test') def get_test(): user_name = 'ログインしているユーザ名' return """ <body> <h2> {{user_name}} </h2> </body> """.format( user_name=user_name )
Pythonで生成する文字列にHTMLを組み込むわけです。しかし、実際のサイトではかなり複雑なHTMLを使用するのでそのようなHTMLをこの方法で用意するのはメンテナンス性に欠きます。そこでテンプレートエンジンを使用します。テンプレートエンジンは先程とは逆にHTMLにPythonのコードを埋め込みます。
templateの使い方
ディレクトリ構成は以下の様になっています。
. ├── template.py └── views └── sample.html
template.py
は以下になっています。
# coding:utf-8 from bottle import run, route, template @route("/") def index(): username = 'test name' return template('sample', username=username) if __name__ == "__main__": run(host='localhost', port=8080, reloader=True, debug=True)
views/sample.html
は以下のHTMLファイルです。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テンプレートエンジン</title> </head> <body> <h2>WELCOME: {{ username }}</h2> </body> </html>
この状態でpython template.py
として起動してから、http://localhost:8080/
にアクセスするとWELCOME: test name
と表示されます。views/sample.html
は見た目上ほとんどHTMLですが{{ username }}
だけが異なります。ここがテンプレートエンジンによって処理され、動的に値が設定されます。
template('sample', username=username)
という部分は以下の流れで動作します。
sample.html
というファイルをviews
配下から捜索sample.html
を読込{{ xxx }}
というテンプレートエンジン用の記法をチェックusername='test name'
を読み込んだ内容に当てはめて置き換え- 置き換え後のHTMLを生成し、クライアントへ返送
なお、sample.html
は拡張子が必ずしもhtml
である必要はなく['tpl', 'html', 'thtml', 'stpl']
の何れかであれば良いです。また、views
というディレクトリも以下の様にbottle.TEMPLATE_PATH
に追加することで変更可能です。
import bottle bottle.TEMPLATE_PATH += ['./other_path']
なお、テンプレートに渡すデータが少ないときはtemplate('sample', username=username)
のように直接指定しても良いですが、数が多い時は以下の様にしたほうが楽です。
@route("/") def index(): context_data = { 'username': 'test name', 'data1': 1, 'data2': 2, 'data3': 3, } return template('sample', **context_data)
templateの記法
bottleに標準で用意されているテンプレートエンジンはSimpleTemplate Engineと呼ばれるものです。このテンプレートエンジンで利用できる記法を確認します。以下の形でデータをテンプレートに渡します。
@route("/") def index(): context_data = { 'username': 'test name1', 'is_admin': False, 'todo_list': [ 'todo1', 'todo2', 'todo3', 'todo4', ] } return template('sample', **context_data)
テンプレート側は以下です。
<body> <h2>WELCOME: {{ username }}</h2> % if is_admin: <p>管理者モード</p> % else: <p>一般モード</p> % end <ul> % for todo in todo_list: <li>{{ todo }}</li> % end </ul> </body>
<h2>WELCOME: {{ username }}</h2>
という箇所は先程からでていましたが、{{ xxx }}
で指定したPythonの変数が展開されます。
%
で始まる行はPythonのコードとして評価されます。ただし、インデントでのブロック表現ができないため% end
でブロックの終了を明示する必要があります。そのため上述例のようにfor
やif
はend
とセットで用いられます。
まとめ
WEBアプリケーションでUI部分で用いられるテンプレートについて簡単にまとめました。bottleのテンプレートエンジンはテンプレートファイルの分割等の高度な機能も用意されていますので詳しくはdocumentを御覧ください。