FastAPI ディレクトリ設計

最近、アプリケーションを開発する際のバックエンドはもっぱら FastAPI を使っています。Python ベースの、軽量で高速なフレームワークです。

実装を繰り返す中で行き着いた、個人的に開発を進めやすいディレクトリ構成をまとめました。
※ただし、個別のファイルの中身に関しては言及するとボリュームが増えてしまうので、本記事では触れません。あくまでも全体感のみをお伝えする内容になります。

まず、下記が全体感です(User と Book がモデルとして存在しているとします)。

# ディレクトリ・ファイル構成全体

├── app
│   ├── __init__.py
│   ├── cruds
│   │   ├── __init__.py
│   │   ├── users.py
│   │   ├── books.py
│   │   └── domains
│   │       ├── __init__.py
│   │       └── search.py
│   ├── database.py
│   ├── main.py
│   ├── models
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── book.py
│   ├── routers
│   │   ├── __init__.py
│   │   ├── users.py
│   │   └── books.py
│   ├── schemas
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── book.py
│   └── utils
│       ├── __init__.py
│       └── logger.py
├── db
│   ├── __init__.py
│   ├── alembic.ini
│   ├── migrations
│   │   ├── README
│   │   ├── env.py
│   │   ├── script.py.mako
│   │   └── versions
│   │       └── <GENERATED_BY_ALEMBIC>.py
│   ├── seed.py
│   └── seeds
│       └── data.dat
├── docker
│   ├── api
│   │   ├── Dockerfile
│   │   └── requirements.txt
│   └── db
│       ├── Dockerfile
│       ├── conf.d
│       │   └── my.cnf
│       └── initdb.d
├── docker-compose.yml
├── log
└── scripts
   ├── init_db.sh
   └── run_server.sh

トップ階層のみを書いてみると、下記のようになります。

# トップレベルディレクトリ・ファイル構成

├── app/ ... アプリケーション(API)のコード群
├── db/ ... マイグレーション・シード用のファイル群
├── docker/ ... Dockerfile(app, db の2種類)
├── docker-compose.yml
├── log ... DBコンテナのログ出力用
└── scripts ... docker-compose での起動スクリプトなど

アプリケーション実装の app/ とデータの db/ を分けるというごく当たり前の構成をしていますが、FastAPI ではマイグレーションに関しては別のライブラリである alembic を用いることが前提になっています。
そして、このようにディレクトリを分けつつ、うまく app/, db/ 双方でモジュールの import をエラーなく行うには、環境変数の PYTHONPATH をいじらなくてはならないことに注意が必要です…

続いて、app/ 内の構成についてです。

└── app
    ├── __init__.py
    ├── cruds ... DBにクエリを投げる処理。routers/内から呼び出される
    ├── database.py ... DBセッションの実装
    ├── main.py ... uvicorn により実行されるファイル
    ├── models ... sqlalchemy を用いたモデル定義
    ├── routers ... @app.get や @router.get などの実装
    ├── schemas ... pydantic を用いたモデルスキーマ定義
    └── utils ... 汎用的なスクリプトなど

ユーザーリクエストからの流れで見ると、main.py => routers/* => cruds/* になります。models/* はDBに保存される型式、schemas/* はユーザーへのレスポンス型式 をそれぞれ指定するものです。

基本的に実装が(ビジネスロジックなどによって)汚染されていくのは cruds/ の中になると思いますが、ビジネスロジックは cruds/domains/* の中にすべて詰め込んでいきます。ロガー・ヘルパーなどの汎用的な実装のみ utils/ に実装していきます。

マイクロサービス化が進んでいる昨今、FastAPIのような軽量なフレームワークは今後需要が高まっていくでしょう。別の機会に、実際のコードも紹介していきたいと思います。

この記事が気に入ったらサポートをしてみませんか?