メインコンテンツへスキップ

Flask の Blueprint を使う

·2 分
ひとりアドベントカレンダー2024 Python Flask
目次

はじめに
#

「OKAZAKI Shogo のひとりアドベントカレンダー2024」の5日目です。 平日限定で続けようとしてましたが、昨日できなかったので・・・ ここまで作った Flask のアプリですが、今後のことも考えてディレクトリ構造を少し変えてみます。

MVT モデル
#

Flask では MVT モデルを採用している。

MVC モデルでは、

  • Model:ビジネスロジックを記述。データベースアクセスを伴うことが多い。
  • View:画面描画を担当。ユーザからの入力も受け付ける。
  • Controller:URL を振り分ける。 View からのデータを Model に渡したり、逆に Model から View にデータを渡す役割を担う。 と言った具合だが、MVT モデルでは、
  • Model : MVC モデルの Model と同じ役割
  • View : MVC モデルの Controller と同じ役割
  • Template : MVC モデルの View と同じ役割 と少し役割が異なる。

アプリ構造の変更
#

app.py にコードが集中しすぎないように、上記の MVT モデルの役割でコードを分割する。以下のような構造に変更する。

 1.
 2|-- Makefile
 3|-- app <-- 名前変更
 4|   |-- __init__.py <-- 処理を追加
 5|   |-- app.py
 6|   |-- index.cgi
 7|   |-- static
 8|   |   `-- css
 9|   |       `-- default.css
10|   |-- templates
11|   |   |-- index.html
12|   |   `-- layout.html
13|   `-- views
14|       `-- index.py <-- 新規作成
15|-- instance
16|   `-- config
17|       `-- dev.py <-- 新規作成
18|-- poetry.lock
19`-- pyproject.toml

Flask の Blueprint(青写真)
#

分割するにあたって、Flask の Blueprint 機能を使う。以下、公式マニュアルの説明:

Blueprintは、関連するviewおよびその他のコードをグループへと編成する方法です。viewおよびその他のコードを直接Flaskアプリケーションに登録するよりも、代わりにそれらをblueprintに登録します。それから、factory関数の中でFlaskアプリケーションが利用可能になったときに、blueprintをFlaskアプリケーションに登録します。

まずは、 __init__.py で config ファイルを読み込み、 Blueprint の登録を行った上で、アプリケーションを作成するように変更する。

__init__.py

 1import os
 2from flask import Flask
 3
 4
 5def create_app():
 6    # appの設定
 7    app = Flask(__name__, instance_relative_config=True)
 8    # configファイルを読み込む
 9    config_path = os.path.join('config', 'dev.py')
10    app.config.from_pyfile(config_path)
11    
12    # Blueprint の登録
13    from app.views.index import index_bp
14
15    app.register_blueprint(index_bp)
16
17    return app

次に、 app.py では、アプリを起動するように変更する。

app.py

1from app import create_app
2
3app = create_app()
4
5if __name__ == '__main__':
6    app.run()

index.py では、 / にアクセスがあった場合の処理を書く。また、「index」という名前の Blueprint も作成する。Blueprintは自分がどこで定義されているか知る必要があるため、__name__ が2番目の引数として渡されている。url_prefix は、 Blueprint と関連付けられる全ての URL の(パス部分の)先頭に付けられる。

index.py

1from flask import Blueprint, render_template
2
3index_bp = Blueprint('index', __name__, url_prefix='/')
4
5
6@index_bp.route("/", methods=["GET", "POST"])
7def index():
8    return render_template('index.html')

最後に、環境ごとの設定を記述するファイルを作成する。とりあえず、開発環境のものだけ。

dev.py

1DEBUG = True

これで起動して、前と同じ動作になっていれば OK。

参考資料
#