Flask でアプリケーションを作る際のメモ(2015 年版)

Flask でアプリケーションを作る際のメモ - Memo の 2015 年版

ディレクトリ構造

.
├── __init__.py
├── app.py
├── configs
│      ├── __init__.py
│      └── settings.py
├── errors.py
├── extensions
│      ├── __init__.py
│      ├── injector.py
│      └── permission.py
├── forms
├── i18n
├── models
│      ├── __init__.py
│      ├── db.py
│      ├── entities
│      └── mappers
├── static
│      ├── css
│      ├── fonts
│      ├── img
│      └── js
├── templates
│      ├── admin
│      └── frontend
├── tests
│      ├── __init__.py
│      ├── factories
│      ├── fixtures
│      └── helper.py
├── utils
│      ├── __init__.py
│      ├── compat.py
│      ├── decorators.py
│      ├── method_rewrite.py
│      └── pagination.py
└── views
    ├── __init__.py
    ├── admin
    └── frontend
app.py アプリケーションファクトリ
configs 設定ファイル
errors.py アプリケーションが使う例外関連
extensions Flask の拡張ライブラリ
injector.py DI 関係(Flask-Injecotr)
permission.py 権限管理(Flask-Principal)
forms WTForms
i18n 国際化関連の翻訳ファイル類
models モデル類(直下はドメインロジック)
db.py SQLALchemy のセッション生成等
entities SQLAlchemy のテーブル類
mappers BPMapper(SQLAlchemy のオブジェクトを JSON に変換)
tests テスト類
factories factory_boy 関連
fixtures Mock類(外部 Web サービスの JSON 等)
helper.py テスト用ヘルパー
utils ユーティリティ
compat.py Python2, 3 の互換関連(Werkzuig からのコピー)
decorators.py デコレータ類
method_rewrite.py HTTP の PUT などを上書き
pagination.py Pagenator
views View 類

アプリケーションの構造は基本的に変らない。
Injector を使いまくってるので、それが増えた。
あとは factory_boy を使うようになったりとか、Python3 に移行したとかが大きな違い。

アプリケーションの起動

app.py は各種 Flask の拡張の初期化や、views(Blueprint)の登録、エラーハンドリングなどを行う。
アプリケーションの起動は Flask-Script 経由で app.py でアプリケーションオブジェクトを生成して起動する。
テストも app.py のアプリケーションオブジェクトを生成して実行する。
セッション周りは元々 Flask-KVSession を使っていて、しばらく Python3 に対応しなかったので、Redis のインタフェースを適当に書いたけど、Flask-KVSession が Python3 に対応したので、元に戻った。

DB 周り

db.py は元々 meta.py とか(Pylons の名残)にしてたけど、直感的じゃないので、db.py にした。
Flask-SQLAlchemy ではなく SQLALchemy を直接使ってるのは、主にマルチデータベース関連のため*1
マイグレーションには Alembic 使ってる。

View と Model の関係

SQLAlchemy のテーブル類は entities というくくりに入れる。
モデルのロジック類は models 直下に入れる。
View からは models 直下のロジックを使う(entities を直接は触らない)。
Flask-Intector が models 以下のロジックを DI で注入してインスタンス化してるので、View から呼び出してテンプレートエンジンにアサインするか、JSON 化して応答する。


リクエストのバリデーションは WTForms か JSON なら jsonschema を使う。
これは View に書いてハンドリングしている。
昔はロジックだからと models のロジックに入れていたが WTForms に依存が出てくるのでやめた。

テスト

factory_boy を使うようになった。
データベースは毎回 setUpClass 内で初期化をしている。
fixtures には Web サービスがあるのなら、それが応答するレスポンスをダミーデータとして mock から使う。
ヘルパーには例えば、ログイン画面の csrf トークンの取得など便利関数があるので、それを使う。


とりあずは小規模なアプリケーションならこれで困っていない。

*1:Flask-SQLAlchemy も対応しているが、意図通り動かなかったため