「bottle」+「jinja2」を使ってサイト構築 1

2018年7月1日

最近は一時期よりは下火になっているものの、PythonでフレームワークといえばDjango。
でもさくっとページを作りたいときにはちょっとがっちりしすぎていて作りづらい。

ということで、最近は bottle を使っている。

ただ、bottle標準のテンプレートエンジンが使い慣れないため、テンプレートエンジンは
Djangoで使われているテンプレートエンジンエンジン jinja2 を使っている。

 

 
サンプルコードはこちら
(次回以降に紹介したコードも含む)
 

bottle、jinja2をインストール

 

virtualenv で切ってbottleをインストールする。

[shell]
$ mkdir python_bottle
$ cd python_bottle
$ virtualenv-3.4 python
$ source python/bin/activate
(python)$ pip install bottle jinja2
[/shell]

 

使い方の確認

以降の説明では、どこからがbottleの機能、もしくはjinja2の機能といった紹介をせず
に説明していく。

ソースファイルを設置するsourceディレクトリを作成する。
また、sourceディレクトリ内にテンプレートファイルを設置するviewsディレクトリと、
スタティックなファイルを設置するstaticディレクトリを作成する。
更に、staticディレクトリ内にjs、css、imgディレクトリを作成する。

[shell]
(python)$ mkdir -p source/{views,static}
(python)$ mkdir -p source/static/{js,css,img}
[/shell]

以下のソースファイル index.py と views内にトップページのテンプレートファイル top.html
を作成する。

[python title="source/index.py"]
# -*- coding: utf-8 -*-

import os
from bottle import route, run
from bottle import TEMPLATE_PATH, jinja2_template as template

# index.pyが設置されているディレクトリの絶対パスを取得
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# テンプレートファイルを設置するディレクトリのパスを指定
TEMPLATE_PATH.append(BASE_DIR + "/views")

# 今回の場合は https://localhost:8080/top にアクセスが来た場合に公開する内容を指定。
# route関数をデコレータとして呼び出し、route関数の引数で/以降のアクセス先を指定する。
@route('/top’)
def top():
return template('top’)

if __name__ == "__main__":
# localhost:8080 で公開するように実行
run(host="localhost", port=8080, debug=True, reloader=True)
[/python]

[html title="source/views/top.html"]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>テストページ</title>
</head>
<body>
テストページ
</body>
</html>
[/html]

記述後、index.pyを実行する。

[shell]
(python)$ python source/index.py
[/shell]

実行後、ブラウザで https://localhost:8080/top にアクセスすると以下のように表示される。

スクリーンショット 2015-05-18 2.04.09

 

 

 

 

 

 

 

 

テンプレートへの変数の渡し方

テンプレートへの変数の渡し方は template関数で行う。

[python]
template(テンプレートファイル名, テンプレート内での変数名1=渡す変数1, テンプレート内で使う変数名2=渡す変数2, …)
[/python]

上で作った index.py と top.html で試す。

[python title="index.py"]
# -*- coding: utf-8 -*-

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

# index.pyが設置されているディレクトリの絶対パスを取得
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# テンプレートファイルを設置するディレクトリのパスを指定
TEMPLATE_PATH.append(BASE_DIR + "/views")

@route('/top’)
def top():

# 配列を渡すための準備
fizzbuzz = []
for i in range(1, 100):

if i % 3 == 0 and i % 5 == 0:
fizzbuzz.append(str(i) + ": fizzbuzz")
elif i % 3 == 0:
fizzbuzz.append(str(i) + ": fizz")
elif i % 5 == 0:
fizzbuzz.append(str(i) + ": buzz")
else:
fizzbuzz.append(str(i))

return template('top’, name="umentu", fizzbuzz=fizzbuzz)

if __name__ == "__main__":
run(host="localhost", port=8080, debug=True, reloader=True)
[/python]

[html title="top.html"]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>テストページ</title>
</head>
<body>
<!–変数を使う場合は、{{}} の中に変数名を記述–>
こんにちは、 {{name}}

<h1>今日のfizzbuzz</h1>
<!–
配列fizzbuzzから1つずつ順番にデータを取り出し、fzbzに代入。
fzbzは単なる変数のため、{{}}で表示
–>
{% for fzbz in fizzbuzz %}
{{ fzbz }}<br />
{% endfor %}
</body>
</html>
[/html]

index.pyを実行したままなら再読込されているはず。
index.pyを停止した場合は再度実行してブラウザでアクセスすると、以下のように表示される。

スクリーンショット 2015-05-18 2.22.47

 

 

 

 

 

 

 

 

 

動的なルーティングの指定

何かというと、https://localhost:8080/top/’username’ を来るように仕向けた場合、
'username’の部分の値を取得して利用する方法のこと。

index.py、top.htmlを次のように書き換える。

[python title="index.py"]
# -*- coding: utf-8 -*-

import os

from bottle import route, run
from bottle import TEMPLATE_PATH, jinja2_template as template
from bottle import static_file

# index.pyが設置されているディレクトリの絶対パスを取得
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# テンプレートファイルを設置するディレクトリのパスを指定
TEMPLATE_PATH.append(BASE_DIR + "/views")

"""
routeは複数指定できる。
上の場合は/top/のあとに何も指定せずにアクセスが来た場合。
下の場合は、/top/の後にユーザー名を指定したアクセスが来た場合。
ルーティングで値を渡す部分に関しては<>で括る。
"""
"""
<>でくくった名前を関数の引数名で渡す。
username="anonymous" としているのは、@routeの上の場合の
ユーザー名の指定がなかった場合にanonymousとして利用するため。
"""
@route('/top/’)
@route('/top/<username>’)
def top(username="anonymous"):

# 配列を渡すための準備
fizzbuzz = []
for i in range(1, 100):

if i % 3 == 0 and i % 5 == 0:
fizzbuzz.append(str(i) + ": fizzbuzz")
elif i % 3 == 0:
fizzbuzz.append(str(i) + ": fizz")
elif i % 5 == 0:
fizzbuzz.append(str(i) + ": buzz")
else:
fizzbuzz.append(str(i))

# name に username の値を渡す。
return template('top’,name=username, fizzbuzz=fizzbuzz)

if __name__ == "__main__":
run(host="localhost", port=8080, debug=True, reloader=True)
[/python]

[html title="top.html"]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>テストページ</title>
</head>
<body>
<!–変数を使う場合は、{{}}の中に変数名を記述–>
こんにちは、 {{name}}

<h1>今日のfizzbuzz</h1>
<!–
配列fizzbuzzから1つずつ順番にデータを取り出し、fzbzに代入。
fzbzは単なる変数のため、{{}}で表示
–>
{% for fzbz in fizzbuzz %}
{{ fzbz }}<br />
{% endfor %}
</body>
</html>
[/html]

ブラウザでアクセスすると以下のようになる。

・usernameを指定しなかった場合
2015-05-19 23.57.25

 

 

 

 

 

 

 

 

 

・usernameを指定した場合
2015-05-19 23.58.15

 

 

 

 

 

 

 

 

 

Djangoに比べると、導入はかなり楽に感じられる。
次回はbootstrapを読み込んだりjQuery使ったりといったstaticな部分から。