クイックスタート

さぁ、始めましょう。本項ではFlaskを起動する方法について紹介します。 Flaskがまだinstallされていないなら、 インストールについて の項を参照してください。

最小規模のアプリケーション例

最小規模のFlaskアプリケーション例を以下に示します。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return "Hello World!"

if __name__ == '__main__':
    app.run()

これを hello.py のような名前で保存し、Pythonインタープリタで実行してください。 アプリケーションに flask.py という名前は付けないこと。Flask自体のファイルと競合してしまうからです。

$ python hello.py
 * Running on http://127.0.0.1:5000/

http://127.0.0.1:5000/ 上で、”Hello World!”と出力されます。

(※注意※ 外部からは見ることができません。下記参照)

では、このコードはどんな処理を行ったのでしょうか?

  1. まず、 Flask クラスをインポートしました。このクラスのインスタンスは WSGIアプリケーションです。 まず、このアプリケーションのモジュール名について述べます。 もしあなたが使うモジュールが一つだけなら、 __name__ を使わなければなりません。 それがアプリケーションとして起動したときとモジュールとしてインポートされたときで名前が異なるからです (アプリケーションとして起動したときは '__main__' 、インポートされたときはそのインポート名)。 もっと詳しく知りたければ、 Flask のドキュメントを参照してください。
  1. 次にインスタンスを生成します。モジュールやパッケージの名前は要りません。 このインスタンスはFlaskがテンプレートファイルやスタティックファイルなどをどこから探すのかを 認識するために必要です。
  1. route() デコレータを使用し、ファンクションを起動するURLをFlaskに教えます。
  1. そのファンクション名は特定のファンクションに対してURLを生成するためにも使われ、 ファンクションはユーザーのブラウザ上で表示したいメッセージを返します。
  1. 最後に run() ファンクションを使い、ローカルサーバーでアプリケーションを実行します。 if __name__ == '__main__': は、そのスクリプトがPyrhonインタープリタから直接実行されたときだけに そのサーバで走り、モジュールとしてインポートされたときには走らないことを保証します。

サーバを停止するには、control-Cを押してください。

外部から見ることができるサーバー

サーバーを走らせた時、そのサーバーが外部ネットワークからではなく あなたのコンピュータだけで利用できていることを確認しましょう。 外部から利用できないのはデフォルトの設定になっています。 デバッグモードでそのアプリケーションのユーザーは誰でも あなたのコンピュータ上でPythonコードを恣意的に実行できてしまうからです。 もし debug モードを使用不可にするか、ネットワーク上の全ユーザを信頼するなら、 サーバーを公共利用にすることも可能です。

run() メソッドの宣言を以下のように変更してください。

app.run(host='0.0.0.0')

これはオペレーティングシステムがパブリックIPを参照する指定です。

デバッグモード

run() メソッドはローカル開発用サーバを立ち上げるのに適していますが、 コードに変更を加えたときは手動でリスタートする必要があり面倒です。 Fraskにはもっと上手いやり方があります。デバッグサポートをサーバに適用すれば、 コード変更に伴って自動でリロードしてくれる上、誤りがあったときに便利なデバッガーが 立ち上がります。

デバッグをするために2つのやり方があります。 どちらも、アプリケーションオブジェクトにフラグを立てるやり方です。

app.debug = True
app.run()

省略もできます。

app.run(debug=True)

どちらでも同じ機能が得られます。

ご注意

インタラクティブデバッガーはフォークした環境では動きません。 そのため、プロダクションサーバではこのデバッガーをほとんど使えません。 大きなセキュリティリスクとなる任意コードの実行を許してしまうことになるので、 プロダクションマシーンでは決して使わないでください

起動中のデバッガーのスクリーンショット:

screenshot of debugger in action

ルーティング

本項はじめに提示した例のように、 route() デコレータは ファンクションとURLをバインドするために使われますが、それだけではありません。 URLを部分的に動的にすることができ、ファンクションにいくつかのルールを付与することもできるのです。

以下に例を示します。

@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello World'

変数ルール

現代のWebアプリケーションは非常に単純明快なURLを持っているため、人々はURLを覚えることができます。 これはネットワーク接続の遅い携帯デバイスから利用されるアプリケーションにとって非常に有用なことです。 もしユーザーがインデックスページを経由せずに直接望んだページにいけるなら、ユーザーは そのページに繰り返し好んで訪れることになるでしょう。

URLに変数部分を付け加えるために、 <variable_name> として特別にセクションをマーキングすることができます。 そのような部分はファンクションへのキーワードアーギュメントとして略記されます。 <converter:variable_name> でルールを特定することにより、コンバーターを特定することもできます。 以下に例を示します。

@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    pass

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    pass

以下のコンバーターが存在することが分かります。

int 整数を受け入れる
float int と同様、浮動小数点を受け入れる
path デフォルト同様だが、スラッシュも受け入れる

固有のURL / リダイレクション

FlaskのURLルールはWerkzeugのルーティングモジュールに基づいています。 そのモジュールの背景にある理念は、見た目が整っていること、且つ、アパッチの動作に 基づいた、以前のサーバによって作られた固有のURLを持つことです。

2つのルールを例に取ります。

@app.route('/projects/')
def projects():
    pass

@app.route('/about')
def about():
    pass

似たように見えますが、URLの 定義 の末尾にスラッシュが入っているという違いがあります。 一つ目のケースでは、 projects という標準的URLの末尾にスラッシュが入っています。 フォルダ表記に似ていますね。頭のスラッシュなしでアクセスすると、Flaskはスラッシュ付きの標準的URLに リダイレクトすることになります。

しかし2番目の例では末尾スラッシュなしでURLが定義されています。そのため、ファイルと似たような挙動を示し、 末尾スラッシュを付けてアクセスすると404エラーとなります。

なぜでしょうか?ユーザがページにアクセスする際に末尾スラッシュを付け忘れてしまっても、 関連URLが働き続けます。この挙動はアパッチや他のサーバーが動く原理と同じことです。 また、そのURLはサーチエンジンが同じページを2回重複してインデックスしないように固有のURLで ありつづけます。

URLビルド

もしURLが一致したら、それも生成することができるのでしょうか?もちろんできます。 URLを特定のファンクションに対してビルドするために、 url_for() ファンクションが使えます。 そのファンクション名は一番目のアーギュメントとなり、いくつかのキーワードアーギュメントを 取ります。そしてそのそれぞれがいくつかのURLルール知られていなURLルールの変数部分と一致します。 不明な変数部分はクエリ変数としてURLに追加されます。以下に例を示します。

>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
...  print url_for('index')
...  print url_for('login')
...  print url_for('login', next='/')
...  print url_for('profile', username='John Doe')
...
/
/login
/login?next=/
/user/John%20Doe

(後述される test_request_context() メソッドも使われています。 基本的には、リクエストを扱っているかどうか、インタラクティブPythonシェル内かどうかを flaskが考えるものです。以下の説明を参照してください。 context-locals).

なぜテンプレートにハードコーディングせずにURLをビルドしたいのでしょうか? 三つの理由があります。

  1. リバーシングは大抵URLをハードコーディングするより説明的です。また、あらゆる場所にある 多くのURLを変更することなく、一息でURLの変更が出来るという大きな利点があります。
  2. URLビルドは特殊文字やUnicodeデータを飛ばす処理を行います。ユーザは特に意識して何かする必要はありません。
  3. もしアプリケーションがURLルートの外にあるなら (例えば / ではなく /myapplication の中にあるとき)、 url_for() で扱うと良いです。

HTTP メソッド

HTTP (Webアプリケーションに使われているプロトコル) には、URLにアクセスする別の方法もあります。 ルートをデフォルトに設定するのは、 GET リクエストに対する答えですが、 それは, methods アーギュメントを route() デコレータに適用することで変えることができます。 以下に例を示します:

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

GET がある時、何もしなくても HEAD が自動的に付与されます。 それによって、It will also make sure that HEAD リクエストが HTTP RFC (HTTPプロトコルを記述しているドキュメント) デマンドのように扱わていることが分かるでしょう。 そのため、HTTPの特定にあたる部分に関して何も考える必要はなくなります。

HTTPメソッドとは何のことか分かりませんか? ご心配なく。 HTTPメソッドとその重要性に関するの簡単な紹介があります:

HTTPメソッドは (しばしば”HTTP verb”とも呼ばれますが) サーバーに、クライアントが要求されたページで 何をしたいか をサーバーに伝えます。以下のようなメソッドが一般的です:

GET
ブラウザはサーバーに以下のことを伝えます: そのページにある情報を get し、それを送ってください! これがおそらく最も一般的なメソッドでしょう。
HEAD
ブラウザはサーバーに以下のことを伝えます: 情報をgetしてください、ただし私には ヘッダー 以外の ページコンテンツには興味ありません。アプリケーションは GET リクエストを受け取ったかのように扱われますが、 やり取りされるのは実際のコンテンツです。Flaskではその扱いを気にする必要が全くありません。 水面下でWerkzeugライブラリが動いてくれているからです。
POST
新しい情報をURLに post したいということをブラウザがサーバーに教えます。 そのURLとサーバーが、データが保存されることと、ただ一度だけ保存されることを保証しなければいけないからです。 これはHTML形式がサーバーとデータ通信する通常の方法です。
PUT
POST に似ていますが、サーバーは、古い値を何度も上書きすることによって 何度もプロシージャを保存するきっかけを作ります。そのどこが便利なのか不可解かもしれませんが、 これを使ういくつかの理由があります。通信中に接続が切れてしまうケースを考えると、 ブラウザとサーバー間のシステムは何も中断させることなく安全に二回目のリクエストを 送らなければなりません。 POST を使えばそれが可能です。一回きりの始動で済むからです。
DELETE
指定された場所から情報を削除します。

HTML4とXHTML1で面白いのは、フォームがサーバーに提示するメソッドは GETPOST だけということです。 しかし、JavaScriptや将来のHTML基準では他のメソッドも同様に使うことができます。さらに言うと、 HTTPは近年非常にポピュラーなものになったので、ブラウザーより多くの内容がHTTPに基づいて通信されます。 (例えばあなたの改訂管理システムはHTTPで通信しているかもしれません)

スタティックファイル

動的なWebアプリケーションはスタティックファイルを必要とします。それは通常CSSやJavaScript のファイルが呼び出されるところです。ウェブサーバーはそれらのファイルをあなたに サーブするように構成されているのが理想ですが、開発中にFlaskもそのような挙動が実現できます。 static という名前のフォルダーをパッケージ内かモジュールの隣に作っておくだけで、 /static がアプリケーション上で呼び出せます。

その部分のURLに対してURLを生成するときは、特別な 'static' URL名を使用します:

url_for('static', filename='style.css')

そのファイルは、ファイルシステム上に static/style.css という名前で保存されます。

レンダリングテンプレート

PythonでHTMLを生成するのはだるい作業です。実際、アプリケーションの安全性を保つために HTMLを管理しなければならないのは煩わしいです。そのため、Flaskは自動的に Jinja2 テンプレートエンジンの設定がされています。

使用可能なテンプレートをレンダリングするために render_template() メソッドを使います。そのテンプレートとテンプレートエンジンに通したい変数に キーワードアーギュメントとして名前を付けるだけで良いのです。 以下にテンプレートをレンダリングする方法の簡単な一例を示します:

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Flaskはテンプレート templates フォルダから探します。そのため、 アプリケーションがモジュールでありテンプレートフォルダがモジュールの隣にあるときは、 それがパッケージであるなら実際はあなたのパッケージ内に存在します:

Case 1: モジュール:

/application.py
/templates
    /hello.html

Case 2: パッケージ:

/application
    /__init__.py
    /templates
        /hello.html

テンプレートを作る際、Jinja2のテンプレートをフル活用することができます。 深く知りたければ、 Jinja2 Template Documentation を参照してください。

以下にテンプレート例を示します:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello World!</h1>
{% endif %}

テンプレートでは、 requestsessiong [#] オブジェクトも get_flashed_messages() ファンクションと同時にアクセスされます。

テンプレートは継承が行われる場合にとても有用です。それがどのような働きによるものなのか知りたければ Template Inheritance パターンドキュメントを参照してください。 基本的にテンプレートの継承では、それぞれのページ(ヘッダー、ナビゲーション、フッターなど) 上のある要素を保持することができます。

自動エスケープも使えます。もし名前にHTMLが含まれていたら自動的にエスケープされます。 変数が信頼でき、それが安全なHTMLであることが分かっていれば(例えばwikiマークアップをHTMLに コンバートするモジュールに起因するもの)、 Markup クラスあるいは テンプレート内の |safe フィルタを使って安全にマークすることができます。 より多くの例は、Jinja2ドキュメントを参照してください。

Markup クラスがどう働くかについて、簡単な紹介があります:

>>> from flask import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup(u'<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup(u'&lt;blink&gt;hacker&lt;/blink&gt;')
>>> Markup('<em>Marked up</em> &raquo; HTML').striptags()
u'Marked up \xbb HTML'

Changed in version 0.5.

[1]g オブジェクトが何者だかあやふやですか?It’s something you これは情報を保存するものです。(g)オブジェクトに関するドキュメントを 参照してください。また、より深く知るには Using SQLite 3 with Flask を参照してください。

リクエストデータへのアクセス

Webアプリケーションにとってクライアントがサーバに送ったデータに反応するのは重要なことだ。 Flaskではこの情報は request というグローバルオブジェクトから供給される。 Python経験者はそのオブジェクトがいかにしてグローバルたりえるのか、どのようにFlaskが スレッドセーフで働くのか、不思議に思うかもしれない。 その答えは、コンテクストローカルである:

コンテクストローカル

内部情報

コンテクストローカルがどのようにして働くか、そのテストをどうやって実装するかを 知りたければ、この項を読んでください。そうでなければ読み飛ばしても構いません。

Flaskのいくつかのオブジェクトはグローバルですが、俗に言うグローバルオブジェクトでは なく、特定のコンテクストに対してローカルなオブジェクトに対するプロキシです。 なんのこっちゃですね。しかし、理解するのは簡単です。

スレッドをハンドルするコンテクストを思い浮かべてください。リクエストが出され、 ウェブサーバは新しいスレッド(もしくは他の、その根底にある、 他の並列システムをスレッドと同様に扱うことができるようなオブジェクト)を立てようとします。 Flaskが内部リクエストを扱おうとするとき、現在のスレッドがアクティブコンテクストであり、現在の アプリケーションとそのコンテクスト(スレッド)に対するWSGI環境をバインドすることが分かります。 アプリケーションが他のアプリケーションを停止することなく起動する賢いやり方です。

これは何を意味するでしょうか?基本的に、これがユニットテストないしその他のケースを 除外したものであるということを完全に無視することができるということです。 ということは、リクエストオブジェクトが無ければ、リクエストオブジェクトに依存するコードは 急停止してしまいます。その解決策は、リクエストオブジェクト自体を新しく作ることと、 それをコンテクストにバインドすることです。ユニットテストに対する最も簡単な解決策は、 test_request_context() コンテクストマネージャーを使用することです。 context manager. In combination with the with ステートメントの組み合わせにおいては、 相互にやりとりできるようにテストリクエストがバインドされます。以下に例を示します:

from flask import request

with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == '/hello'
    assert request.method == 'POST'

WSGI環境全体を request_context() メソッドに通すやり方も考えられます:

from flask import request

with app.request_context(environ):
    assert request.method == 'POST'

リクエストオブジェクト

リクエストオブジェクトはAPIの項で記述されており、ここでは詳細について述べません ( request を参照してください)が、最もよく使われるオペレーション についてだけご説明します。まず、requestを flask モジュールからimportしてください:

from flask import request

現在のリクエストメソッドは method 属性を使うことによって 使用できます。フォームデータ( POST または PUT リクエストでやりとりされるデータ)に アクセスするには、 form 属性を使うことができます。 以下に上記2属性を使用した例を示します:

@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # this is executed if the request method was GET or the
    # credentials were invalid

form 属性にキーが存在しなかった場合どうなるのでしょうか?その場合、 特殊な KeyError が起こります。 それは通常の KeyError と同じように受け取れますが、 受け取らなかった場合、HTTP 400 Bad Requestのエラーページが代わりに表示されます。 そのため、多くの場合敢えてその問題を扱う必要はありません。

URL (?key=value)で提起されたパラメータにアクセスするには、 args 属性を使うことができます:

searchword = request.args.get('q', '')

get を使うか、 KeyError を受け取ることでURLパラメータにアクセスすることをお勧めします。 なぜなら、ユーザーにとって不便があった場合にURLが変更されて400 bad request のページが 出てきてしまうことがあるからです。

オブジェクトに対するメソッドと属性の一覧は、 request ドキュメントを参照してください。

ファイルアップロード

Flaskを使えば、ファイルアップロードをとても簡単に扱うことができます。 enctype="multipart/form-data" 属性をHTMLフォームにセットするのだけ忘れないでください。 そうしないとブラウザがファイル通信できなくなってしまいます。

アップロードされたファイルはメモリーまたはファイルシステムのテンポラリロケーションに 格納されます。それらのファイルにはリクエストオブジェクト上の files 属性を 参照することでアクセスすることができます。アップロードされたファイルはそれぞれ そのディクショナリに格納されています。そしてそれは通常のPythonの file オブジェクト と同じような挙動を示しますが、ファイルシステムやサーバー上のファイルを格納する save() メソッドも含まれています。どのように働くか、 簡単な例を示します:

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

アプリケーションにアップロードされる前にそのファイルがクライアントでどう名付けられたか 知りたければ、 filename 属性にアクセスしてください。 ただし、この値は決して信頼できないものにもなり得ることを念頭に置いておいてください。 もしファイルをサーバーに格納するためにクライアントのファイルネームを使うなら、 Werkzeugが提供する secure_filename() ファンクションを通してください:

from flask import request
from werkzeug import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
    ...

さらに深い例は、 Uploading Files サンプルを参照してください。

リダイレクトとエラー

ユーザーをどこか別の使用可能な場所へリダイレクトするには、 redirect() ファンクションが 使えます。 さらに、エラーコード abort() ファンクションで素早くリクエストを 中断することができます。どのように動くのか、以下に例を示します:

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

これはかなり要点を得ない例です。なぜならユーザーがインデックスからアクセス不可能なページに リダイレクトされるからです(401はアクセス拒否の意味です)。しかし、どのように動いているか を知るという意味では良い例です。

それぞれのエラーコードにおいて、白黒のエラーページが現れるのがデフォルトになっています。 もしエラーページをカスタマイズしたければ、 errorhandler() デコレータを 使うことができます:

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

render_template() コールの後の 404 に着目してください。 これはFlaskにそのページのステータスコードが404、すなわちnot foundとなる べきであることを伝えています。デフォルトでは200は全ての通信が上手く行ったことを表します。

セッション

リクエストオブジェクトの他にも、 session と呼ばれるセカンドオブジェクトが あります。それによってあるリクエストから次のリクエストまで、固有のユーザーごとに 情報を格納することができます。これはcookieのトップに実装されており、cookieを暗号の ように表示することができます。これにより、ユーザーはcookieのコンテンツを修正せずに 、また表示に使われた秘密鍵を知られることなく、ただ見ることができます。

セッションを使うためには秘密鍵を設定しなければなりません。以下に、セッションが どのように働くかの例を示します:

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if its there
    session.pop('username', None)
    return redirect(url_for('index'))

# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

ここで、 escape() はテンプレートエンジンを使わない時に エスケープされます (この例を参照)。

How to generate good Secret Keys

The problem with random is that it’s hard to judge what random is. And a secret key should be as random as possible. Your operating system has ways to generate pretty random stuff based on a cryptographic random generator which can be used to get such a key:

>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'

Just take that thing and copy/paste it into your code and you’re done.

メッセージフラッシング

良いアプリケーションやユーザインターフェースは、フィードバックがつきものです。 もしユーザーが十分なフィードバックを得なければ、そのアプリケーションが嫌いになる だけで終わってしまいます。Flaskはフィードバックをユーザーに与える非常に単純な方法を フラッシングシステムを用いて提供します。フラッシングシステムは、基本的には リクエストの末尾でメッセージを記録することと、次のリクエストだけにアクセスすることを 可能にします。これは通常、その動作を行うレイアウトテンプレートと結合されます。

メッセージをフラッシュさせるために、 flash() メソッドが使えます。 また、そのメッセージを保持するために get_flashed_messages() もテンプレート上で 用意されています。使用例は、 Message Flashing を参照してください。

ログ取り

New in version 0.3.

扱っているデータが正しいと思っていたら、実はそうでなかったという状況もあり得ます。 例えばHTTPリクエストをサーバーに送信するクライアントサイドのコードがあったとします。 そして、それは明らかに不正なものだったとします。それはユーザーのデータの焼き戻し、あるいは そのクライアントコードの失敗の要因となります。こういった場合大抵 400 Bad Request を返して おけばよいのですが、そうでない場合もあり、コードが動き続けなければならないことがあります。

怪しい出来事のログを取りたい。このとき、ロガーを重宝します。 Flask0.3ではロガーが事前設定されています。

ログを呼び出す例を示します:

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

付け加えられている logger は、標準のログ取り様式 Logger です。 より深い情報は、stdlibの公式ドキュメントを参照してください。