[Dd]enzow(ill)? with DB and Python

DBとか資格とかPythonとかの話をつらつらと

Pythonで一番小さいWEBフレームワークbottle.py その4(static_file,erropage)

前回はGETやPOSTについてまとめました。今回はROUTING STATIC FILESを中心にまとめます。

静的?動的?

STATIC FILEは静的ファイルという意味です。逆に動的もあります。どう違うのでしょうか。とてもざっくりいうと下のイメージです。

type memo
静的 同じURLで同じ内容が戻る。固定ページや画像、動画等。URLから割出されるOS上の固定ファイルを戻す
動的 ページの基本的な部分は共通だが、アクセスユーザ等に応じて内容が一部変わる。サーバ等でHTMLを組み立てて戻す

たとえば、前回つくったログインのサンプルはログイン後にログインユーザ名が表示されていましたので動的ページと言えます。逆に静的ファイルとしてはjscssjpg等が挙げられます。

Apache等のWEBサーバやTomcat等のJavaのAPサーバはほとんどがデフォルトで静的ファイルを配信する機能がありますが、Bottle等ほとんどのWEBアプリケーションフレームワークは静的ファイルをデフォルトでは配信しません。静的ファイルを配信するための設定を事前にしておく必要があります。

bottleの静的ファイル配信

静的ファイルを配信するためには、static_file関数を使用します。URLで指定されたファイルと同名のOS上のファイルを戻すには以下のようになります。

# coding:utf-8
from bottle import run, route, static_file

# /static/hoge.js なら./static/hoge.jsを戻す
@route('/static/<filename>')
def server_static(filename):
    return static_file(filename, root='./static/')

if __name__ == "__main__":
    # テスト用のサーバをlocalhost:8080で起動する
    # reloader=Trueにより、ソースを書き換えると自動的に再起動される
    run(host='localhost', port=8080, reloader=True)

static_file関数は、root=で親ディレクトリを指定し渡したファイル名と結合してアクセス先を特定します。

現在のディレクトリ構成は以下です。

(bottle_sample) denzownoMacBook-Pro:bottle_sample denzow$ tree .
.
├── app.py
├── bottle.py
└── static             <- 静的ファイルを配置するディレクトリ
    ├── js
    │   └── sample2.js <- 配信したいファイル
    └── sample1.js     <- 配信したいファイル

では、http://localhost:8080/static/sample1.js にアクセスしてみましょう。

alert("this is sample1.js");

と表示されたと思います。うまくいきました。続いて、以下にsample2.jsにアクセスしてみます。

http://localhost:8080/static/js/sample2.js

これはうまくいかずにError: 404 Not Foundが戻ります。これはルーティングの設定に問題があるからです。@route('/static/<filename>')ワイルドカードで指定している<filename>の部分は/を含むことはできません。/を含んだマッチを実現するにはpathのフィルタを使用します。以下のように書き換えましょう。

@route('/static/<file_path:path>')
def server_static(file_path):
    return static_file(file_path, root='./static/')

これで http://localhost:8080/static/js/sample2.js にアクセスするとちゃんとsample2.jsの内容が戻るようになりました。

alert("this is sample2.js");

このserver_static関数はサンプルですが、Bottle.pyでアプリを作る際は必ず入れてしまっても良いと思います。

エラーページの変更

さて、今回はちょくちょく404のエラーページを見ましたね。出ていた画面はBottle標準のものですがこれをカスタマイズすることもできます。GitHubとかはタコだかネコだかのエラーページがでますね。

エラーページをカスタムするには@errorアノテーションを使用します。404に対応するカスタムページを作るのは以下のようなコードになります。

from bottle import run, route, static_file, error

@error(404)
def error_404(error):
    # errorはHTTPErrorオブジェクト
    error_code = error.status
    return template(
        "this is 404 custom page.<br>{{error_code}}",
        error_code=error_code,
    )

とりあえず実在しないページにアクセスすると以下のようなページが表示されました。

this is 404 custom page.
404 Not Found

こんな感じに普通のページと同じようにtemplate等も使えるので好きなページを作ることができます。

まとめ

今回は静的ファイルや404ページのカスタムする方法がわかりました。JSやCSSがこれで配信できるのでページのレイアウト等も少しずつ触れていきたいと思います。