Python + Bottle + Jinja2で、Jinja2のカスタムフィルターを使う

Python + Bottleを使っている中で、PHPnl2brのようなものがほしくなりました。

ただ、データとしては<br>タグを持ちたくないので、HTML側で何とかできないかを調べてみました。すると、BottleのJinja2テンプレートでもカスタムフィルターが使えることが分かったため、試してみました。

 

環境

 

Jinja2のインストール

BottleにはJinja2が含まれていないため、pipでインストールします。

>pip install jinja2
...
Successfully installed MarkupSafe-0.23 jinja2-2.8

 

実装

Python

BaseTemplate.settings.update()を使って、カスタムフィルターを定義します。

今回は単純なフィルターだったので、lambda式を使うことにしました。
Pythonの無名関数(lambda)の使い方 - Life with Python

また、jinja2テンプレートはbottle.pyと同じディレクトリに置きました。他のディレクトリに置きたい場合は、TEMPLATE_PATHにパスを追加します。

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from bottle import route, request, run
from bottle import jinja2_template as template

# 必要に応じて、jinja2テンプレートがあるディレクトリを追加
from bottle import TEMPLATE_PATH
TEMPLATE_PATH.append("./path/to/templates")

# jinja2のfilterを設定
from bottle import BaseTemplate
BaseTemplate.settings.update({'filters': {'nl2br': lambda content: content.replace('\n', '<br>')}})


@route('/', method="GET")
def form():
    return template('bottle_filter.html', result="")
    
@route('/', method="POST")
def display():
    input_with_newline = request.forms.get('input_with_newline').decode('utf-8')
    return template('bottle_filter.html', result=input_with_newline)

# 略

 

Jinja2テンプレート側

<div>{{ result|nl2br }}</div>のように、表示させたいデータに対して |を使って定義したカスタムフィルターを指定します。

<form method="post" action="/">
    <fieldset>
        <legend>情報</legend>
        <label for="value">改行を含むデータ</label>
        <textarea name="input_with_newline" id="value"></textarea>
        <input type="submit" name="submit" id="submit" value="送信" />
    </fieldset>
</form>
<div>
    <p>nl2brあり</p>
    <div>{{ result|nl2br }}</div>
</div>
<div>
    <p>nl2brなし</p>
    <div>{{ result }}</div>
</div>

 

結果

改行を含むデータとして

一行目
二行目

をフォームに入力してみました。

結果のHTMLソースを見たところ、カスタムフィルターありの場合、<br>タグが挿入されていました。

<div>
    <p>nl2brあり</p>
    <div>一行目
<br>二行目</div>
</div>
<div>
    <p>nl2brなし</p>
    <div>一行目
二行目</div>
</div>

 

ソースコード

  • bottle_filter.py
  • bottle_filter.html

GitHubに上げておきました。
thinkAmi-sandbox/Bottle-sample