コンポーネント@Flask¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. App¶
Flaskクラス¶
▼ Flaskクラスとは¶
WSGIアプリケーションの実行に関するメソッドを持つ。
クラスの引数に、グローバル変数の『__name__
』あるいはエントリーポイントのパスを直接的に設定する。
環境変数のFLASK_APP
で指定したエントリーポイントでは、必ずFlaskクラスのインスタンスを作成する必要がある。
from flask import Flask
app = Flask(__name__)
# src/app.py
# app = Flask(src)
route
メソッド¶
▼ route
メソッド¶
Flaskクラスにエンドポイントを追加する。
from flask import Flask
app = Flask(__name__)
PREFIX_FOO = "foo"
@app.route("/{PREFIX}/show", methods=["GET"])
def show():
# DBへのアクセス処理
...
run
メソッド¶
▼ run
メソッドとは¶
設定されたルーティングを元に、WerkzeugによるWebサーバーを起動する。
開発環境のみで推奨される方法である。
from flask import Flask
app = Flask(__name__)
PREFIX_FOO = "foo"
@app.route("/{PREFIX}/show", methods=["GET"])
def show():
# DBへのアクセス処理
app.run()
▼ 引数¶
引数 | 説明 |
---|---|
debug |
エラーログをブラウザ上に表示するか否かを設定する。 |
host |
受信する通信のIPアドレスを設定する。全てのIPアドレスの場合は、0.0.0.0 とする。 |
load_dotenv |
dotenv パッケージを読み込むか否かを設定する。これを有効化すれば、他の引数は環境変数から設定できる。 |
port |
インバウンド通信を待ち受けるポート番号を設定する。 |
use_reloader |
ホットリロードを有効化するか否かを設定する。 |
02. 環境変数¶
App¶
▼ FLASK_APP¶
アプリケーションのエントリーポイントを設定する。
FLASK_APP の値 |
説明 |
---|---|
module:name |
モジュール名 (ファイル名) とインスタンス名を設定する。 |
module:function() |
モジュール名 (ファイル名) と関数名を設定する。 |
module |
モジュール名 (ファイル名) を設定する。 |
file.py |
ファイル名を設定する。 |
▼ SESSION_COOKIE_NAME¶
Cookie
ヘッダーでセッションデータ (ペイロード + タイムスタンプ + 署名) を運ぶ時のキー名を設定する。
デフォルトでは、キー名はsession
になる。
# レスポンス
200 OK
---
Set-Cookie: session=*****
# リクエスト
# レスポンスのSet-Cookieヘッダーによって、Cookieヘッダーをつける必要がある
GET /foo/
---
Cookie: session=*****
▼ SECRET_KEY¶
Cookie
ヘッダーでペイロードとタイムスタンプを署名するためのキーを設定する。
03. ベストプラクティス¶
アプリケーションファクトリーパターン¶
▼ アプリケーションファクトリーパターンとは¶
Pythonのコードを配置するディレクトリに__init__.py
ファイルを配置し、ここでFlaskクラスのインスタンスを作成するメソッドを定義する。
# __init__.py
from flask import Flask
def create_app():
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World'
return app
▼ エントリーポイント¶
プロジェクトのルートディレクトリに、create_app
メソッドを実行するエントリーポイント (例:main.py
ファイル) を配置する。
名前空間を判定する条件分の外でcreate_app
メソッドを実行しないと、uwsgiがapp変数を見つけられない。
from src import create_app
app = create_app()
if __name__ == '__main__':
app.run()
▼ 開発環境と本番環境の違い¶
本番環境では、アプリケーションの実行にrun
関数とflask run
コマンドを使用しないようにする。
代わりに、uWSGIやgunicornを使用して、エントリーポイントの関数を直接的にコールする。
本番環境と開発環境を同様にするために、本番環境のみでなく開発環境でもコマンドを使用しないようにしても良い。
04. ビルトイン関数¶
requests¶
▼ get¶
HTTPリクエストを送信する。
from flask import Flask
app = Flask(__name__)
def getProductReviews(product_id, headers):
for _ in range(2):
try:
url = reviews['name'] + "/" + reviews['endpoint'] + "/" + str(product_id)
res = requests.get(url, headers=headers, timeout=3.0)
except BaseException:
res = None
if res and res.status_code == 200:
request_result_counter.labels(destination_app='reviews', response_code=200).inc()
# 200ステータスの場合、そのままブラウザにレンダリングする
return 200, res.json()
elif res is not None and res.status_code == 403:
request_result_counter.labels(destination_app='reviews', response_code=403).inc()
# 403ステータスの場合、ユーザーにわかりやすいメッセージに変えて、ブラウザにレンダリングする
return 403, {'error': 'Please sign in to view product reviews.'}
elif res is not None and res.status_code == 503:
request_result_counter.labels(destination_app='reviews', response_code=503).inc()
# 503ステータスの場合、ユーザーにわかりやすいメッセージに変えて、ブラウザにレンダリングする
return 503, res.json()
else:
status = res.status_code if res is not None and res.status_code else 500
request_result_counter.labels(destination_app='reviews', response_code=status).inc()
# 500ステータスの場合、ユーザーにわかりやすいメッセージに変えて、ブラウザにレンダリングする
return status, {'error': 'Sorry, product reviews are currently unavailable.'}
@app.route('/')
def home():
product_id = 0
headers = getForwardHeaders(request)
user = session.get('user', '')
product = getProduct(product_id)
# detailsサービスにリクエストを送信する
detailsStatus, details = getProductDetails(product_id, headers)
logging.info("[" + str(detailsStatus) + "] details response is " + str(details))
# reviewsサービスにリクエストを送信する
reviewsStatus, reviews = getProductReviews(product_id, headers)
logging.info("[" + str(reviewsStatus) + "] reviews response is " + str(reviews))
# いずれかのマイクロサービスでアクセストークンの検証が失敗し、401ステータスが返信された場合、ログアウトする
if detailsStatus == 401 or reviewsStatus == 401:
logging.info("[" + str(401) + "] access token is invalid.")
redirect_uri = url_for('logout', _external=True)
return redirect(redirect_uri)
response = app.make_response(render_template(
'productpage.html',
detailsStatus=detailsStatus,
reviewsStatus=reviewsStatus,
product=product,
details=details,
reviews=reviews,
user=user))
return response
session¶
▼ セッションデータの作成¶
セッションデータを作成し、レスポンスのSet-Cookie
ヘッダーに保管する。
from flask import Flask, session
app = Flask(__name__)
session['username'] = user
▼ セッションデータの取得¶
レスポンスのSet-Cookie
ヘッダーやリクエストのCookie
ヘッダーから、セッションデータを取得する。
from flask import Flask, session
app = Flask(__name__)
session['username'] = request.form['username']
username = session['username']
session.get
関数でも取得でき、デフォルト値を設定できる。
from flask import Flask, session
app = Flask(__name__)
session.get('username', 'None')
▼ セッションデータの保持期間¶
app.permanent_session_lifetime
で、セッションデータの保持期間を設定できる。
from flask import Flask, session
app = Flask(__name__)
app.permanent_session_lifetime = timedelta(days=5)
セッションデータを作成する前にsession.permanent
を有効化しておくと、セッションデータの保持期間を無期限にできる。
この場合、保持期間は無視される。
from flask import Flask, session
app = Flask(__name__)
session.permanent = True
session['username'] = user
url_for¶
▼ external¶
ホスト名とデフォルトのプロトコル名 (HTTP) のあるURLを作成する。
from flask import Flask, url_for
app = Flask(__name__)
with app.test_request_context():
# http://localhost/
print(url_for('index', _external=True))
▼ scheme¶
ホスト名と指定したプロトコル名のあるURLを作成する。
from flask import Flask, url_for
app = Flask(__name__)
ith app.test_request_context():
# https://localhost/
print(url_for('index', _external=True, _scheme='https'))