FlaskでHello World! はなんとなく動いたと思いますが、この記事では Flask の基本を説明します。
Flaskとは
Flask は Python でWEBアプリを構築するための枠組みを提供するもので、マイクロフレームワークと呼ばれます。Python のフレームワークには Django 等もありますが、Flask はシンプルで学習コストが低いことが特徴です。
FlaskでHello World! でやったように、ネット記事を参考にいくつかサンプルを動かしてみることをお勧めします。そうすることで Flask の動きを体感することができます。
さらにちゃんと勉強したい人は Flask の 公式ページ を見てください。Flask 公式ページ クイックスタート に基本的な文法が説明されているので、サンプルプログラムと突き合せれば Flask の仕組みがわかります。
Hello World! 再び
それでは Hello World! に戻って、どの様なプログラムだったのか確認しましょう。
1 2 3 4 5 6 7 8 9 10 11 |
# coding: utf-8 from flask import Flask app = Flask(__name__) @app.route('/') def main(): return 'Hello world!' if __name__ == '__main__': app.run(debug=True, host='0.0.0.0') |
1行目の # coding: utf-8 はソースプログラムの文字コードを宣言するもので、Python の構文です。Flask のプログラムはその次からです。
1 2 |
from flask import Flask app = Flask(__name__) |
まず、Flask をインポートしています。これで Flask の機能が使えるようになります。次の行では、Flaskクラスのインスタンスを作っています。app という変数名が慣例的に使われます。__name__ という特殊な変数名には Python のモジュール名が自動的に入っており、アプリ実行時に Flask が静的ファイルにアクセスするときに参照されます。
1 |
@app.route('/') |
これは route() デコレータと呼ばれるもので、WEBアプリが呼ばれたURLに応じて、処理すべき内容を振り分けるものです。WEBアプリを呼び出すには https://ドメイン名/hoge のようにURLを記述しますが、ドメイン名よりも後ろの部分(例えば /hoge)を引数に渡します。Hello World! の例では route() デコレータはひとつだけ存在し、ドメイン名のルート、つまり ‘/’ が指定されたときに以降に書かれたプログラムが実行されます。
1 2 |
def main(): return 'Hello world!' |
デコレータで振り分けられた後、実際に実行される内容は関数としてプログラミングします。この例では、関数は ‘Hello World!’ という文字列を返すだけです。
1 2 |
if __name__ == '__main__': app.run(debug=True, host='0.0.0.0') |
Python のプログラムは、そのプログラムが直接起動された場合や、import文で他のプログラムから参照された場合など、異なる環境で実行される可能性があります。最初の if 文、if __name__ == ‘__main__’: で今このプログラムそのものが直接起動されたものであることを判断できます。そのときには app インスタンスに記述されたプログラムがサーバープログラムとして起動します。ポート番号はデフォルトで 5000番が割り当てられます。デバッガを有効にしている場合は、セキュリティのために実行しているコンピュータ以外からのアクセスを拒否します。それを許可するために host=’0.0.0.0′ のオプションを指定していますが、自分のパソコン上で動かす場合には不要です。
FlaskでWEBページを制御する
もう少し複雑なサンプルを試してみましょう。
- app.py
デコレータが3ヶ所にあり、3種類のWEBページに処理を分岐させています。URLに続けて ‘/’、’/page1’、’/page2’ を指定するとそれぞれの処理を実行する関数が呼ばれます。各関数の中ではデバッグ情報を出力した後、render_template() という関数を呼んでいます。これは雛形となる index.html を加工してブラウザに返す処理です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# coding: utf-8 from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): print('DEBUG: Reached to Menu page') return render_template('index.html', page='menu') @app.route('/page1') def page1(): print('DEBUG: Reached to Page1') return render_template('index.html', page='page1') @app.route('/page2') def page2(): print('DEBUG: Reached to Page2') return render_template('index.html', page='page2') if __name__ == '__main__': app.run(debug=True) |
- index.html
ブラウザに表示するHTMLの雛形です。普通のHTMLと違うのは {% 〜 %} という形で処理を書き分けているところです。render_template() の引数に応じて、実際にブラウザに返す HTML を加工します。この処理はFlaskと一緒に使われるJinja2というライブラリが行っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<!--index.html--> <!DOCTYPE html> <html> <head> <title>Flask Sample</title> </head> <body> <h2>Flaskテスト</h2> {% if page == "menu" %} これはFlaskのテストです。</br> <a href="/page1">Page1へ移動します。</a> {% elif page == "page1" %} これはPage1です。</br> <a href="/page2">Page2へ移動します。</a> {% elif page == "page2" %} これはPage2です。</br> <a href="/">最初のページへ戻ります。</a></br> <a href="/page1">Page1へ戻ります。</a> {% else %} ここには来ないはずです。 {% endif %} </body> </html> |
- requirements.txt
このサンプルアプリを動作させるために必要なライブラリのリストです。このサンプルならFlaskだけあれば動作します。
1 |
Flask==1.1.2 |
上記の3ファイルをこのように配置してください。index.html はソースコードよりも1段下のディレクトリに置いてください。
1 2 3 4 5 |
app (作業ディレクトリ) +-- app.py (ソースコード) +-- requirements.txt +-- templates (この名前は常に "templates") +-- index.html (templatesの下にHTMLを配置) |
アプリを実行するには、仮想環境を作成して、必要なライブラリをインストール、そしてアプリを起動します。
1 2 3 4 5 |
$ cd app $ virtualenv sample_env $ source sample_env/bin/activate $ pip3 install -r requirements.txt $ python3 app.py |
localhost:5000 にアクセスすると動作するはずです。
静的なデータファイルを使う
Flaskでは静的な(動作に応じて変化することのない)ファイル、例えばアイコンの画像データのようなものは static という名前のディレクトリに配置する事になっています。先程の例にイメージデータを追加してみましょう。
- index.html
1行追加します。データファイルへのパスは /static で定義していることに注意してください。
1 2 3 4 |
{% if page == "menu" %} <img src="/static/imagedata.png"></br> これはFlaskのテストです。</br> <a href="/page1">Page1へ移動します。</a> |
- データファイル
下のように /static ディレクトリの下に配置します。
1 2 3 4 5 6 |
app +-- app.py +-- templates +-- index.html +-- static (この名前は static で固定) +-- imagedata.jpg |
※イラストは「いらすとや」様からお借りしました。
コメント