Flaskではアプリの構成をさまざまな方法で行える。その基本からインスタンスフォルダを利用するまでざっくりと見ていこう。
連載「Visual Studio Codeで始めるPythonプログラミング」
前回は、データベースに保存されたデータをWeb APIを介してクライアントに返送する方法を幾つか示した。今回は、Flaskアプリの構成方法について見ていこう(タイトルとは裏腹にVisual Studio Codeの話題はほとんど出てこない)。
Webアプリに限らず、アプリには構成(configuration)が必要になる。開発環境でデバッグ実行をしているのか、プロダクション環境で実行をしているのかなど、その実行環境によって、アプリの振る舞いを変更する必要があるからだ。
Flaskアプリでは、幾つかの方法でその構成を行える。一番簡単なのは、本連載で既に見てきたものだ。以下に例を示す(「VS CodeとFlask-SQLAlchemyでデータベース操作 」の「最小限のアプリ」より)。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db/sample.db"
db = SQLAlchemy(app)
これはapp.configオブジェクトを利用して、SQLALCHEMY_DATABASE_URIの値を「sqlite:///db/sample.db」に設定するものだ。
小規模なアプリや本連載で紹介しているような「サンプル」であれば、上のようにハードコードしても問題ないだろう。だが、環境に応じて構成を変える必要があるのであれば、Flaskではさまざまな方法でアプリを構成できるようになっている。大ざっぱにいえば、Flaskアプリは以下のような方法で構成可能だ。
このうち、インスタンスフォルダを使った構成は、アプリに固有の機密性を持った情報をアプリ本体からは隔離しておくことを目的としている(シークレットキーなどをアプリ本体からは独立したフォルダに保存して、ソースコード管理の対象から外すといった利用法を想定している)。
本稿ではこれらの方法の幾つかを紹介しよう。
これまでのToDoリストアプリから外れて、今回は以下のようなアプリを作成する。今回はWindows版のPython 3.6.5を使用して仮想環境「myenv」を作成した後に、そこに「pip install flask」コマンドでFlaskをインストールしている。また、動作確認もWindows版のVS Codeで行っている。
今回は「パッケージ形式」の構成を取り、アプリ本体は__init__.pyファイルに記述する。パッケージ名は「flask_app」となっている。その基本コードは次の通りだ。
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html", config=app.config.items())
アプリのルートへのリクエストを受け取ると、app.configオブジェクトに登録されている構成値をテンプレートを利用して表示するだけの簡単なものだ。構成値の表示に使用するテンプレートは次のようになっている。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Configuration setted up by Flask</title>
</head>
<body>
{% for key, value in config %} {{ key }}: {{ value }}<br> {% endfor %}
</body>
</html>
[デバッグ]ビューで歯車アイコンをクリックしてlaunch.jsonファイルを作成したら、Flask用のデバッグ構成にある「FLASK_APP」環境変数の値をパッケージ名である「flask_app」に変更するのを忘れないようにしよう(あるいは、コマンドパレットから[Python: Create Terminal]コマンドを実行して仮想環境を有効にしたターミナルを開いてから、FLASK_APP環境変数の値を設定し、「flask run」コマンドでアプリを起動してもよい)。
{
"version": "0.2.0",
"configurations": [
// …… 省略 ……
{
"name": "Python: Flask (0.11.x or later)",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "flask_app"
},
"args": [
"run",
"--no-debugger",
"--no-reload"
]
},
// …… 省略 ……
]
}
この状態でアプリを実行したところを以下に示す。
表示されている構成値(組み込みの構成値)については、「Builtin Configuration Values」を参照されたい(英語ページ)。重要なのは、ENVやDEBUGといった構成値は環境変数FLASK_ENV/FLASK_DEBUGを用いて設定するものであり、アプリ内のコードでこれらを設定しても「思った通りの動作とはならない」ことだ(上記ページに明記されている)。
では、このアプリを使って、各種の構成方法を試していこう。
app.config.from_pyfileメソッドを使うと、構成値を「キー=値」形式で記述したファイルを基に構成値を設定できる。以下に例を示す。
from flask import Flask, render_template
app = Flask(__name__)
app.config["SOME_CONFIG"] = "configured in __init__.py"
app.config.from_pyfile("config.cfg", silent=True)
@app.route("/")
def index():
return render_template("index.html", config=app.config.items())
SOME_CONFIG = "configured in config.cfg"
ここでは、__init__.pyファイルで"SOME_CONFIG"の値を"configured in __init__.py"に設定した上で、構成を記述したconfig.cfgファイルでも「"configured in config.cfg"」のようにして構成している。from_pyfileメソッドのsilent引数にTrueを渡しているが、これはファイルがなかったときに例外を発生しないようにするものだ。この状態でアプリを実行すると、次のようになる。
一番下の行を見ると分かるように、構成値が上書きされたことが分かる(もちろん、2行の順序を入れ替えれば、後の構成で先の構成が上書きされる)。ここから分かるのは、アプリの実行環境によらず共通の構成値を何らかの方法で設定した後に、実行環境ごとに異なる構成を行うといったことがFlaskでは可能ということだ。
ファイルから構成値を読み込むにはfrom_envvarメソッドも使える。これは引数に指定した環境変数の値を基に読み込み対象のファイルを決定するものだ。よって、開発時と運用時で環境変数が指すファイルを別個にすることで、基本構成をそれぞれの設定で上書きしたり、環境に固有の構成を行ったりできる。ここではanother_config.cfgファイルを作成して、環境変数ANOTHER_CONFIG_FILEにそのファイルを指定してみよう。
from flask import Flask, render_template
app = Flask(__name__)
app.config["SOME_CONFIG"] = "configured in __init__.py"
app.config.from_pyfile("config.cfg", silent=True)
app.config.from_envvar("ANOTHER_CONFIG_FILE")
@app.route("/")
def index():
return render_template("index.html", config=app.config.items())
SOME_CONFIG = "configured in another_config.cfg"
ANOTHER_CONFIG = "another config"
実行結果を以下に示す。
from_jsonメソッドも同様で、JSON形式で書かれた構成ファイルを読み込ませるのに使用できる(興味のある方は試してみよう)。次にPythonオブジェクトを使用した構成について見ていこう。
Copyright© Digital Advantage Corp. All Rights Reserved.