Web

[Python] Bottleでテンプレートを使用する方法

Bottleは軽量なPythonのWebフレームワークで、テンプレートエンジンを使用してHTMLを動的に生成できます。

bottleにはデフォルトでSimpleTemplateEngineが組み込まれており、{{変数}}の形式で変数を埋め込むことが可能です。

テンプレートを使用するには、bottle.template()関数を使います。

テンプレートファイルは.tpl形式で保存し、@routeデコレータでルートを定義した後、template()関数でテンプレートをレンダリングします。

簡単な概要

Bottleは、Pythonで書かれたシンプルで軽量なWebフレームワークです。

特に小規模なアプリケーションやプロトタイプの開発に適しており、単一のファイルで完結するため、導入が非常に簡単です。

Bottleは、RESTfulなルーティング、テンプレートエンジン、静的ファイルの提供など、Webアプリケーションに必要な基本機能を備えています。

さらに、Bottleは依存関係が少なく、他のライブラリやフレームワークと組み合わせて使用することも容易です。

これにより、開発者は迅速にアプリケーションを構築し、デプロイすることが可能です。

特に、学習や実験を目的としたプロジェクトにおいて、そのシンプルさと柔軟性が評価されています。

目次から探す
  1. Bottleでテンプレートを使用する準備
  2. Bottleでテンプレートを使った基本的な例
  3. テンプレートにデータを渡す方法
  4. テンプレートのカスタマイズ
  5. Bottleでのフォーム処理とテンプレート
  6. 静的ファイルとテンプレートの連携
  7. Bottleテンプレートのデバッグと最適化
  8. Bottleテンプレートの応用例
  9. まとめ

Bottleでテンプレートを使用する準備

テンプレートエンジンの概要

テンプレートエンジンは、HTMLなどの文書を動的に生成するためのツールです。

プログラム内でデータを埋め込むことにより、ユーザーに対してカスタマイズされたコンテンツを提供できます。

Bottleでは、デフォルトで SimpleTemplate というシンプルなテンプレートエンジンが使用されており、Pythonの文法に似た構文で記述できます。

これにより、開発者は直感的にテンプレートを作成し、データを埋め込むことが可能です。

Bottleにおけるテンプレートの役割

Bottleにおけるテンプレートは、主に以下の役割を果たします。

役割説明
コンテンツの分離ビジネスロジックと表示ロジックを分けることで、コードの可読性を向上させる。
再利用性の向上同じテンプレートを複数の場所で使い回すことができ、メンテナンスが容易になる。
動的コンテンツ生成ユーザーの入力やデータベースの情報に基づいて、動的にHTMLを生成する。

テンプレートファイルの作成方法

Bottleでテンプレートを使用するには、まずテンプレートファイルを作成します。

通常、.tpl.htmlの拡張子を持つファイルを作成し、HTMLの中に埋め込む変数や制御構文を記述します。

以下は、基本的なテンプレートファイルの例です。

<!-- example.tpl -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ heading }}</h1>
    <p>{{ message }}</p>
</body>
</html>

Bottleのテンプレートディレクトリの指定

Bottleでは、テンプレートファイルを格納するディレクトリを指定する必要があります。

これにより、Bottleは指定された場所からテンプレートを読み込むことができます。

以下のように、Bottleオブジェクトを作成する際に、template_pathを設定します。

from bottle import Bottle, run, template
app = Bottle()
app.template_path.insert(0, 'templates')  # テンプレートディレクトリを指定
# ルートエンドポイントの定義
@app.route('/')
def index():
    return template('example.tpl', title='サンプル', heading='こんにちは', message='Bottleのテンプレートを使用しています。')
run(app, host='localhost', port=8080)

この例では、templatesというディレクトリにexample.tplファイルを格納し、Bottleがそのテンプレートを使用できるように設定しています。

Bottleでテンプレートを使った基本的な例

template()関数の使い方

Bottleでは、template()関数を使用してテンプレートをレンダリングします。

この関数は、テンプレートファイル名と、必要に応じてテンプレートに渡すデータを引数として受け取ります。

以下は、template()関数の基本的な使い方の例です。

from bottle import Bottle, run, template
app = Bottle()
@app.route('/')
def index():
    return template('example.tpl', title='サンプル', heading='こんにちは', message='Bottleのテンプレートを使用しています。')
run(app, host='localhost', port=8080)

この例では、example.tplというテンプレートファイルを指定し、titleheadingmessageという変数をテンプレートに渡しています。

テンプレートファイルの構造

テンプレートファイルは、HTMLの基本構造を持ちながら、埋め込む変数や制御構文を含むことができます。

以下は、example.tplの構造の例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ heading }}</h1>
    <p>{{ message }}</p>
</body>
</html>

このテンプレートでは、{{ title }}{{ heading }}{{ message }}が変数として埋め込まれています。

これらは、template()関数で渡されたデータに基づいて動的に置き換えられます。

変数の埋め込み方法

テンプレート内で変数を埋め込むには、{{ variable_name }}という形式を使用します。

例えば、以下のように変数を埋め込むことができます。

<p>ようこそ、{{ user_name }}さん!</p>

この場合、user_nameという変数がtemplate()関数で渡されると、テンプレート内でその値が表示されます。

テンプレート内での制御構文(if文、for文)

Bottleのテンプレートでは、制御構文を使用して条件分岐やループ処理を行うことができます。

以下は、if文とfor文の例です。

if文の例

% if is_logged_in:
    <p>ログインしています。</p>
% else
    <p>ログインしていません。</p>
% end

この例では、is_logged_inという変数がTrueの場合は「ログインしています。」と表示され、Falseの場合は「ログインしていません。」と表示されます。

for文の例

<ul>
% for item in item_list:
    <li>{{ item }}</li>
% end
</ul>

この例では、item_listというリストの各要素をループ処理し、リスト項目として表示します。

これにより、動的に生成されたリストを簡単に作成できます。

テンプレートにデータを渡す方法

Python側でのデータ準備

Bottleでテンプレートにデータを渡すためには、まずPython側で必要なデータを準備します。

データは辞書形式で用意することが一般的です。

以下は、ユーザー情報を含むデータの準備の例です。

from bottle import Bottle, run, template
app = Bottle()
@app.route('/')
def index():
    user_data = {
        'user_name': '太郎',
        'age': 25,
        'hobbies': ['読書', '映画鑑賞', '旅行']
    }
    return template('example.tpl', **user_data)
run(app, host='localhost', port=8080)

この例では、user_dataという辞書にユーザー名、年齢、趣味のリストを格納しています。

**user_dataを使うことで、辞書のキーが変数名としてテンプレートに渡されます。

template()関数でのデータ渡し

template()関数を使用して、準備したデータをテンプレートに渡します。

先ほどの例では、**user_dataを使って、辞書の内容を展開して渡しています。

これにより、テンプレート内で各変数を直接使用できるようになります。

return template('example.tpl', **user_data)

このようにすることで、user_nameagehobbiesといった変数がテンプレート内で利用可能になります。

テンプレート内でのデータの表示

テンプレート内では、渡されたデータを埋め込むことで、動的にコンテンツを生成できます。

以下は、example.tplの一部で、データを表示する方法の例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ユーザー情報</title>
</head>
<body>
    <h1>{{ user_name }}さんのプロフィール</h1>
    <p>年齢: {{ age }}歳</p>
    <h2>趣味</h2>
    <ul>
    % for hobby in hobbies:
        <li>{{ hobby }}</li>
    % end
    </ul>
</body>
</html>

このテンプレートでは、{{ user_name }}{{ age }}、および{% for hobby in hobbies %}を使用して、Python側で準備したデータを表示しています。

これにより、ユーザーのプロフィール情報が動的に生成され、ブラウザに表示されます。

テンプレートのカスタマイズ

テンプレートの継承

Bottleでは、テンプレートの継承を使用して、共通のレイアウトを持つ複数のテンプレートを効率的に管理できます。

親テンプレートを作成し、子テンプレートでその内容を拡張することで、コードの重複を避けることができます。

継承する場合はjinja2_templateを使用します。

以下は、親テンプレートの例です。

<!-- base.html -->
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
</head>

<body>
    <header>
        <h1>私のウェブサイト</h1>
    </header>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        <p>© 2023 私のウェブサイト</p>
    </footer>
</body>

</html>

子テンプレートでは、base.tplを継承し、block contentを埋めることができます。

<!-- child.html -->
{% extends "base.html" %}
{% block content %}
    <h2>こんにちは、{{ user_name }}さん!</h2>
    <p>あなたの年齢は{{ age }}歳です。</p>
{% endblock %}

これらのテンプレートを配置して、以下のプログラムを実行すると、親テンプレートを継承したページを表示できます。

from bottle import Bottle, run
from bottle import jinja2_template as template

app = Bottle()

# ルートエンドポイントの定義
@app.route('/')
def index():
    # 表示するユーザーデータ
    user_data = {
        'title': 'ユーザー情報',
        'user_name': '太郎',
        'age': 25
    }
    # child.html を使ってテンプレートをレンダリング
    return template('child.html', **user_data)

# アプリケーションを起動
run(app, host='localhost', port=8080)
テンプレートの表示例

テンプレートのパーシャル(部分テンプレート)

パーシャルテンプレートは、再利用可能な部分を別のテンプレートファイルとして切り出す方法です。

これにより、コードの重複を減らし、メンテナンスを容易にします。

部分テンプレートを使用する場合はjinja2_templateを使用します。

from bottle import Bottle, run
from bottle import jinja2_template as template

app = Bottle()
@app.route('/')
def index():
    return template('main.tpl')
run(app, host='localhost', port=8080)

例えば、ナビゲーションバーをパーシャルとして作成することができます。

<!-- navbar.tpl -->
<nav>
    <ul>
        <li><a href="/">ホーム</a></li>
        <li><a href="/about">アバウト</a></li>
        <li><a href="/contact">お問い合わせ</a></li>
    </ul>
</nav>

このパーシャルを他のテンプレートで使用するには、template()関数を使って読み込みます。

<!-- main.tpl -->
{% include "navbar.tpl" %}
<h1>メインコンテンツ</h1>
<p>ここにメインの内容が入ります。</p>

テンプレートでのフィルタリング

Bottleのテンプレートでは、フィルタリングを使用してデータを加工することができます。

例えば、文字列を大文字に変換したり、リストの要素を結合したりすることが可能です。

以下は、フィルタリングの例です。

<p>大文字: {{ user_name | upper }}</p>  <!-- user_nameを大文字に変換 -->
<p>趣味: {{ hobbies | join(", ") }}</p>  <!-- hobbiesリストをカンマ区切りで表示 -->

このように、フィルタを使うことで、テンプレート内でデータを簡単に加工できます。

カスタムフィルタの作成

Bottleでは、独自のカスタムフィルタを作成することもできます。

これにより、特定のデータ処理を簡単に行うことができます。

以下は、カスタムフィルタの作成方法の例です。

from bottle import Bottle, run, template
app = Bottle()
# カスタムフィルタの定義
def reverse_string(s):
    return s[::-1]
# フィルタを登録
app.template_filters['reverse'] = reverse_string
@app.route('/')
def index():
    return template('example.tpl', user_name='太郎')
run(app, host='localhost', port=8080)

この例では、reverse_stringというカスタムフィルタを作成し、app.template_filtersに登録しています。

テンプレート内でこのフィルタを使用することで、文字列を逆順に表示できます。

<p>逆順: {{ user_name | reverse }}</p>  <!-- user_nameを逆順に表示 -->

このように、カスタムフィルタを使うことで、テンプレート内でのデータ処理を柔軟に行うことができます。

Bottleでのフォーム処理とテンプレート

フォームの作成と表示

Bottleを使用してフォームを作成するには、HTMLの<form>タグを使用します。

以下は、ユーザー名と年齢を入力するシンプルなフォームの例です。

テンプレートファイルにフォームを追加します。

<!-- form.tpl -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ユーザー情報フォーム</title>
</head>
<body>
    <h1>ユーザー情報を入力してください</h1>
    <form action="/submit" method="post">
        <label for="user_name">ユーザー名:</label>
        <input type="text" id="user_name" name="user_name" required><br><br>
        
        <label for="age">年齢:</label>
        <input type="number" id="age" name="age" required><br><br>
        
        <input type="submit" value="送信">
    </form>
</body>
</html>

このフォームは、ユーザー名と年齢を入力するためのフィールドを持ち、送信ボタンをクリックすると/submitエンドポイントにデータがPOSTされます。

フォームデータの受け取り

フォームから送信されたデータは、Bottleのrequestオブジェクトを使用して受け取ります。

以下は、フォームデータを受け取るためのエンドポイントの例です。

from bottle import Bottle, run, template, request
app = Bottle()
@app.route('/')
def show_form():
    return template('form.tpl')
@app.route('/submit', method='POST')
def submit_form():
    user_name = request.forms.get('user_name')  # ユーザー名を取得
    age = request.forms.get('age')  # 年齢を取得
    return template('result.tpl', user_name=user_name, age=age)
run(app, host='localhost', port=8080)

この例では、/submitエンドポイントでPOSTリクエストを受け取り、request.forms.get()を使用してフォームデータを取得しています。

フォームデータをテンプレートに渡す方法

受け取ったフォームデータをテンプレートに渡すことで、ユーザーに入力内容を表示することができます。

以下は、結果を表示するためのテンプレートの例です。

<!-- result.tpl -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>結果</title>
</head>
<body>
    <h1>入力された情報</h1>
    <p>ユーザー名: {{ user_name }}</p>
    <p>年齢: {{ age }}歳</p>
</body>
</html>

このテンプレートでは、user_nameageの変数を使用して、ユーザーが入力した情報を表示しています。

submit_form関数で取得したデータをtemplate()関数を通じて渡すことで、動的に内容が生成されます。

このように、Bottleを使用してフォームを作成し、データを受け取り、テンプレートに渡すことで、ユーザーとのインタラクションを実現できます。

静的ファイルとテンプレートの連携

静的ファイルの提供方法

Bottleでは、静的ファイル(CSS、JavaScript、画像など)を提供するために、static_file()関数を使用します。

静的ファイルを格納するディレクトリを指定し、特定のURLパスにマッピングすることで、ブラウザからアクセスできるようにします。

以下は、静的ファイルを提供するための基本的な設定の例です。

from bottle import Bottle, run, static_file, template
app = Bottle()
# 静的ファイルを格納するディレクトリ
@app.route('/static/<filepath:path>')
def server_static(filepath):
    return static_file(filepath, root='./static')
@app.route('/')
def index():
    return template('index.tpl')
run(app, host='localhost', port=8080)

この例では、/static/<filepath:path>というルートを定義し、static_file()関数を使用して./staticディレクトリ内のファイルを提供しています。

テンプレートでの静的ファイルの参照

静的ファイルをテンプレート内で参照するには、提供したURLパスを使用します。

以下は、CSSファイルをテンプレートに組み込む例です。

<!-- index.tpl -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>静的ファイルの例</title>
    <link rel="stylesheet" href="/static/style.css">  <!-- CSSファイルの参照 -->
</head>
<body>
    <h1>静的ファイルとテンプレートの連携</h1>
    <p>このページはBottleを使用して作成されています。</p>
</body>
</html>

この例では、<link>タグを使用して、/static/style.cssというパスでCSSファイルを参照しています。

これにより、スタイルが適用されます。

CSSやJavaScriptの組み込み

静的ファイルにはCSSだけでなく、JavaScriptファイルも含めることができます。

以下は、JavaScriptファイルをテンプレートに組み込む例です。

<!-- index.tpl -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>静的ファイルの例</title>
    <link rel="stylesheet" href="/static/style.css">  <!-- CSSファイルの参照 -->
</head>
<body>
    <h1>静的ファイルとテンプレートの連携</h1>
    <p>このページはBottleを使用して作成されています。</p>
    <button id="myButton">クリックしてメッセージを表示</button>
    
    <script src="/static/script.js"></script>  <!-- JavaScriptファイルの参照 -->
</body>
</html>

この例では、<script>タグを使用して、/static/script.jsというパスでJavaScriptファイルを参照しています。

これにより、ボタンをクリックしたときにメッセージを表示する機能を追加できます。

// script.js
document.getElementById('myButton').addEventListener('click', function() {
    alert('ボタンがクリックされました!');
});

このように、Bottleを使用して静的ファイルを提供し、テンプレート内で参照することで、スタイルやインタラクティブな機能を持つWebページを簡単に作成できます。

Bottleテンプレートのデバッグと最適化

テンプレートのデバッグ方法

Bottleでテンプレートをデバッグする際は、エラーメッセージやログを活用することが重要です。

テンプレート内でのエラーは、通常、ブラウザに表示されるエラーページに記録されます。

以下は、デバッグを行うための基本的な方法です。

  1. エラーメッセージの確認: テンプレート内でエラーが発生した場合、Bottleはエラーメッセージを表示します。

これにより、どの行でエラーが発生したかを特定できます。

  1. debugモードの有効化: Bottleをデバッグモードで実行することで、詳細なエラーメッセージを得ることができます。

以下のように、run()関数debug=Trueを指定します。

   run(app, host='localhost', port=8080, debug=True)
  1. ログの出力: Bottleのロギング機能を使用して、エラーや警告をログファイルに記録することもできます。

これにより、後から問題を分析することが可能です。

テンプレートのキャッシュ機能

Bottleでは、テンプレートのキャッシュ機能を利用することで、パフォーマンスを向上させることができます。

キャッシュを有効にすると、同じテンプレートが再度レンダリングされる際に、以前の結果を再利用することができます。

これにより、処理時間を短縮できます。

キャッシュを有効にするには、以下のように設定します。

from bottle import Bottle, run, template
app = Bottle()
# キャッシュを有効にする
app.template_lookup.cache = True
@app.route('/')
def index():
    return template('example.tpl')
run(app, host='localhost', port=8080)

この設定により、テンプレートが変更されない限り、キャッシュされた結果が使用されます。

ただし、開発中はキャッシュを無効にしておくことをお勧めします。

パフォーマンス向上のためのベストプラクティス

Bottleでのテンプレートのパフォーマンスを向上させるためのベストプラクティスは以下の通りです。

ベストプラクティス説明
テンプレートの最適化不要な計算や処理をテンプレート内で行わない。データは事前に準備しておく。
静的ファイルの圧縮CSSやJavaScriptファイルを圧縮して、読み込み時間を短縮する。
キャッシュの利用テンプレートのキャッシュ機能を活用し、再利用可能な部分をキャッシュする。
不要なリクエストの削減必要なデータのみをリクエストし、無駄なデータの送受信を避ける。
CDNの利用静的ファイルをCDN(コンテンツ配信ネットワーク)でホスティングし、読み込み速度を向上させる。

これらのベストプラクティスを実践することで、Bottleアプリケーションのパフォーマンスを向上させ、ユーザーに快適な体験を提供することができます。

Bottleテンプレートの応用例

複数ページのWebアプリケーションの作成

Bottleを使用して複数ページのWebアプリケーションを作成することは非常に簡単です。

各ページに対して異なるルートを定義し、それぞれのページに対応するテンプレートを用意します。

以下は、ホームページとアバウトページを持つシンプルなアプリケーションの例です。

from bottle import Bottle, run, template
app = Bottle()
@app.route('/')
def home():
    return template('home.tpl')
@app.route('/about')
def about():
    return template('about.tpl')
run(app, host='localhost', port=8080)

この例では、home.tplabout.tplという2つのテンプレートを用意し、それぞれのルートに対応させています。

テンプレートファイルは以下のようになります。

<!-- home.tpl -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ホームページ</title>
</head>
<body>
    <h1>ホームページ</h1>
    <p>ようこそ!</p>
    <a href="/about">アバウトページへ</a>
</body>
</html>
<!-- about.tpl -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>アバウトページ</title>
</head>
<body>
    <h1>アバウトページ</h1>
    <p>このアプリケーションはBottleを使用して作成されています。</p>
    <a href="/">ホームページへ</a>
</body>
</html>

テンプレートを使ったAPIレスポンスの生成

Bottleでは、テンプレートを使用してAPIレスポンスを生成することも可能です。

JSON形式のレスポンスを生成する際に、テンプレートを利用して動的なデータを埋め込むことができます。

以下は、ユーザー情報をJSON形式で返すAPIの例です。

from bottle import Bottle, run, template, response
app = Bottle()
@app.route('/api/user/<user_id>')
def get_user(user_id):
    # ユーザー情報のサンプルデータ
    user_data = {
        '1': {'name': '太郎', 'age': 25},
        '2': {'name': '花子', 'age': 30}
    }
    
    user = user_data.get(user_id, {'name': '不明', 'age': 0})
    
    response.content_type = 'application/json'
    return template('user.tpl', user=user)
run(app, host='localhost', port=8080)

テンプレートファイルuser.tplは以下のようになります。

{
    "name": "{{ user.name }}",
    "age": {{ user.age }}
}

このようにすることで、指定されたユーザーIDに基づいて動的にJSONレスポンスを生成できます。

テンプレートを使ったメール送信機能の実装

Bottleを使用して、テンプレートを使ったメール送信機能を実装することも可能です。

メールの本文をテンプレートで生成し、SMTPを使用して送信します。

以下は、メール送信の基本的な例です。

from bottle import Bottle, run, template
import smtplib
from email.mime.text import MIMEText
app = Bottle()
@app.route('/send_email/<recipient>')
def send_email(recipient):
    subject = "こんにちは!"
    body = template('email_template.tpl', name=recipient)
    
    msg = MIMEText(body)
    msg['Subject'] = subject
    msg['From'] = 'your_email@example.com'
    msg['To'] = recipient
    # SMTPサーバーの設定
    with smtplib.SMTP('smtp.example.com', 587) as server:
        server.starttls()
        server.login('your_email@example.com', 'your_password')
        server.send_message(msg)
    return "メールを送信しました!"
run(app, host='localhost', port=8080)

メールテンプレートemail_template.tplは以下のようになります。

こんにちは、{{ name }}さん!
このメールはBottleを使用して送信されています。

このように、Bottleを使用してテンプレートを活用したメール送信機能を実装することで、動的なコンテンツを含むメールを簡単に送信できます。

まとめ

この記事では、Bottleフレームワークを使用してテンプレートを活用する方法について詳しく解説しました。

具体的には、テンプレートの基本的な使い方から、データの渡し方、静的ファイルとの連携、さらには応用例として複数ページのWebアプリケーションやAPIレスポンスの生成、メール送信機能の実装まで幅広く取り上げました。

これらの知識を活用することで、より効果的なWebアプリケーションを構築することが可能になりますので、ぜひ実際に手を動かして試してみてください。

関連記事

Back to top button
目次へ