概要
この記事は、Flaskアプリについて、どういうディレクトリ構成ならびにファイル構成にするのが良いのか、という点について世間一般はどうしてるのかと調べてみたメモ書きです。
まぁ、頑張ってつくりこめばつくりこむほど、DjangoとかRailsとかに寄っていくんだろうなぁ……とは思ってます。
注) 有用なこと書いてなくても許してくださぃ
Flask解説サイトでお勧めされていたディレクトリ構成
ExploreFlask というサイトを確認すると、多少複雑なプロジェクトを作るなら、モデルやフォーム用のクラスを作るべきで、
複数のモジュールを繋ぎ合わせたPythonパッケージとして作るのが良いから、以下のような構成にすると良い的な事が書いてありました。
config.py
requirements.txt
run.py
instance/
config.py
yourapp/
__init__.py
views.py
models.py
forms.py
static/
templates/
各ファイル/ディレクトリについては、以下の表のような感じだそうです。
ファイル/ディレクトリ名 | 使い方 |
---|---|
run.py | 開発用サーバの実行用スクリプトでプロダクション用としては使わない |
requirements.txt | 依存するパッケージを書く |
config.py | 設定変数を格納したファイル |
/instance/config.py | APIキーやデータベースのURIなど、バージョン管理に含めない設定変数を格納したファイル |
/yourapp/ | アプリの格納用 |
/yourapp/__init__.py | アプリの初期化用スクリプトで、様々なコンポーネントを読み込む |
/yourapp/view.py or /yourapp/views/ | routeを定義するファイルもしくはディレクトリ |
/yourapp/models.py or /yourapp/models/ | アプリのモデル(のクラス)を定義するファイルもしくはディレクトリ |
/yourapp/forms.py (or /yourapp/forms/ ? ) | フォームの定義をするファイル(もしくはディレクトリ?) (なぜかこれだけ参考サイトの表からディレクトリが消えてました) |
/yourapp/static/ | 公開用のCSS, JavaScript, 画像等のアプリで公開すべきファイル置き場 |
/yourapp/templates | Jinja2テンプレートを置くんだ (なぜJinja2決めうちなんざましょ……) |
に書くということのようです。
なお、さらに複雑なアプリの場合、さらに分割するのもアリなようです。
……@app.cli.command
で定義できるようなcliなコマンドとかはどこに置くんですかね? また別ファイルでしょうか?
あと、どうでもいいですが、 __init__.py
が表の中で強調表示になっていて(単なるエスケープ忘れ)イラっとしました。
Blueprintsをつかってみた
とここまで書いたように、ある程度複雑なアプリを書く場合はファイル等を分割して書く方が良い(というのは、ある程度のプログラムを書いた人なら感覚的に当然と思えるかと思う)のですが、
Flaskアプリで色々と分割しだす場合、Blueprints というのを使うのが良いようです。
こちらのサイトの説明を拝借すると、「Flaskアプリに適用できるようなビュー、テンプレート、静的ページなどのコレクションを定義できる仕組み」のようです。
まぁ、実際に使ってみた方が理解がはやい感じ。
まずはblueprintのオブジェクトを作るところからのようです。
from flask import Blueprint
general = Blueprint('general', __name__)
@general.route('/')
def hello():
return 'hello'
@general.route('/about')
def about():
return 'about'
Blueprint
モジュールの Blueprint()
を使って作成できました。
Blueprint()
の引数ですが、オブジェクトにつけたい名前と __name__
を引数にするのが良いようです。
普通のFlaskのアプリと同じように、デコレータを使ってroute定義していくようです。
さて、ではこの作成したblueprintオブジェクトをどのように使うかという点なんですが、以下のようにFlaskオブジェクトの regiseter_blueprint()
メソッドという、そのまんまなメソッドを使うようです。
from flask import Flask
from .views.general import general
app = Flask(__name__)
app.register_blueprint(general)
これで、いつものようにサーバーを動かすと、いつものように http://localhost:5000/ や http://localhost:5000/about/ が表示されるようになりました。
% export FLASK_APP=hoge
% export FLASK_DEBUG=true
% python3 -m flask run
これだけだと、あんまり嬉しさがわからないんですが、blueprintを使うメリットが以下のようなコードを書くと「ふーむ」という感じになりました。
from flask import Flask
from .views.general import general
app = Flask(__name__)
app.register_blueprint(general, url_prefix='/hoge')
ミソは、 register_blueprint()
に渡している url_prefix
という引数です。
これで先程 http://localhost:5000/ と http://localhost:5000/about/ で見えていたページが、それぞれ http://localhost:5000/hoge/ と http://localhost:5000/hoge/about/ で見えるようになりました。
なお、 url_prefix
は Blueprint オブジェクトの作成時に Blueprint()
に同名の引数としても渡してもいけるようですが、サイトでもお勧めされているように、registerの時につけてあげる方がわかりやすそうですかねぇ。
なお、 url_prefix
には変数を書いても良いそうです。
具体例は以下のような感じ。
from flask import Blueprint
general = Blueprint('general', __name__)
@general.route('/')
def hello(user):
return 'hello %s' % user
@general.route('/reverse')
def about(user):
return user[::-1]
from flask import Flask
from .views.general import general
app = Flask(__name__)
app.register_blueprint(general, url_prefix='/<user>')
他にも、テンプレートや静的ファイルの場所も Blueprint()
への引数で(登録時はどうなんでしょう?)設定できたりと、まだ色々と機能がありそうです。
所管
やっぱりRailsとかはディレクトリ構成が良く考えられてるんだなぁ、と思いました。
が、こういうのを自分で触ってからの方が理解しやすそうな気がします。
以前Rebuild.fmというPodcastで「Railsをいきなり触ると大変だからSinatraを勧めてみた」と伊藤直也さんがおっしゃっていたのは、的確なんだなぁ、とも。
とにもかくにも、まずは自分が作りかけているFlaskのアプリについて、ちょっと書き直してみようと思います。