FastAPIのディレクトリ構成の最適解を知りたいッッ!
記事を書いた背景
普段インターン先でFastAPIを用いたAPI構築業務をしている.
先日仲間とハッカソンに参加した際にFastAPIでバックエンド担当となったのだが、せっかく一から全てを自分で決めることができるということで、作り始める前にFastAPIでの最適なディレクトリ構成を探す旅に出た.今回は備忘録も兼ねて、旅の結果をここに書き留めておく.
FastAPIとは
FastAPI は、Pythonの標準である型ヒントに基づいてPython 3.6 以降でAPI を構築するための、モダンで、高速(高パフォーマンス)な、Web フレームワークです。
>>FastAPI公式
この記事の想定読者
- FastAPIチュートリアルを読んだことがある人
- 上記記事レベルの実装なら調べながらであればできる人
- FastAPIで初めて中規模以上のアプリケーション開発を行う人
- FastAPIで作成されたアプリケーションのメンテナンス性が悪くて困っている人
前提
今回の開発ではDockerは用いず、githubでの管理を前提としたディレクトリ構成となっている.
この記事はプログラムの内容面での話ではないのであまり関係ないかもしれないが、開発環境や各バージョン情報は以下の通り.
結論
いきなり結論だが、今回のハッカソン開発においての最適なディレクトリ構成図(全体像)は以下のようになった.
app-backend/
├ src/
│ ├ assets/
│ │ └ //image-files
│ ├ crud/
│ │ ├ __init__.py
│ │ └ //crud-files
│ ├ database/
│ │ ├ seedings/
│ │ │ ├ __init__.py
│ │ │ └ //seeding-files
│ │ ├ __init__.py
│ │ ├ database.py
│ │ └ master_seeding.py
│ ├ routers/
│ │ ├ __init__.py
│ │ └ //routing-files
│ ├ schemas/
│ │ ├ __init__.py
│ │ └ //schema-files
│ ├ services/
│ │ ├ __init__.py
│ │ └ //service-files
│ ├ __init__.py
│ ├ dependencies.py
│ ├ main.py
│ └ models.py
├ tests/
│ ├ integration/
│ │ ├ __init__.py
│ │ └ //integration-test-files
│ ├ unit/
│ │ ├ __init__.py
│ │ └ //unit-test-files
│ ├ __init__.py
│ ├ conftest.py
│ └ dependencies.py
├ (.env)
├ .env.sample
└ .gitignore
# ()内表記は.gitignore対象.
# /で終わるものはディレクトリを表す.
# //で始まる表記は追加するファイルの内容を表す.
はい、今この図を見て気絶しそうになった人は、一旦意識を戻して次へ進もう.
この図は基本的にはディレクトリの構成図であるが、図中に記述してあるpythonファイル[*~.py]は、FastAPIアプリケーションとしての最小構成に必要なファイルとなっている.
以下ではそれぞれのディレクトリについて、"何がどう便利なのか"を詳しく説明していく.
1層目のディレクトリ構成
先ほどの図はディレクトリ構成図の全体像だったが、数が多くて見づらいため、まずは第1層から見ていこう.
app-backend
ディレクトリ直下だけを抜き出したのが以下の図である.
app-backend/
├ src/
├ tests/
├ (.env)
├ .env.sample
└ .gitignore
# /で終わるものはディレクトリを表す.
各ディレクトリ/ファイルについての詳細は以下の通り.
名称 | type | 詳細 |
---|---|---|
src | directory | アプリのソースコード全般を格納.app という名称だったりもする. |
tests | directory | アプリのテストコードファイルを格納. |
.env | ignore-file | アプリ内で使用する環境変数を記述するファイル.このファイルにはクラウドサービスのシークレットキー等、外にもれたらとんでもないことになる情報を記述するため、GitHub上にはアップロードしない(.gitignoreファイルで指定する). |
.env.sample | file | 先の.envファイルにおける入力が必要な"項目名"のみを記載するためのファイル.通常このファイルをGitHub上にアップロードし、クローン後に必要項目を記入して.env とリネームして使う. |
.gitignore | file | このファイル内に記述したファイルorディレクトリはGitHub上にアップロードされなくなる(無視される).* でワイルドカードが使用できる. |
2層目のディレクトリ構成
次に、第1層の各ディレクトリの内部構成をそれぞれ抜き出して解説していく.
srcディレクトリ
srcディレクトリ内では、アプリケーションのソースコードを記述していく.
srcディレクトリ内部のディレクトリ構成は以下の通り.
app-backend/
└ src/
├ assets/
├ crud/
├ database/
├ routers/
├ schemas/
├ services/
├ __init__.py
├ dependencies.py
├ main.py
└ models.py
# /で終わるものはディレクトリを表す.
名称 | type | 詳細 |
---|---|---|
assets | directory | アプリで使用する画像データなどを格納. |
crud | directory | DBのcrud操作に関する処理を記述したファイルを格納. |
database | directory | DB設定に関する処理を記述したファイルを格納. |
routers | directory | ルーティング後のエンドポイントを記述したファイルを格納. |
schemas | directory | データのスキーマ定義を行うファイルを格納. |
services | direvtory | crud操作に関係のない関数を記述したファイルを格納. |
__init__.py | file | __init__ファイルの使い方が分からない人はとりあえず作っておく.(今後この__init__.pyファイルは図中にのみ記載する.) |
dependencies.py | file | 依存性注入に関する記述をしたファイルを格納. |
main.py | file | エンドポイントに関する設定を行うファイル.このファイルがFastAPIアプリケーションの中心となる. |
models.py | file | 今回はsqlalchemyというpythonのORMを行うことができるライブラリを使用したため、このファイル内でDBモデル設計を行う. |
>>1層目のディレクトリ構成に戻る
>>2層目のディレクトリ構成に戻る
testsディレクトリ
testsディレクトリ内では、アプリケーションのテストコードを記述していく.
testsディレクトリ内部のディレクトリ構成は以下の通り.
app-backend/
└ tests/
├ integration/
├ unit/
├ __init__.py
├ conftest.py
└ dependencies.py
名称 | type | 詳細 |
---|---|---|
integration | directory | 主にアプリケーションの総合テストを記述したファイルを格納. |
unit | directory | 主にアプリケーションの単体テストを記述したファイルを格納. |
conftest | file | テストに関する設定や、各テストの事前/事後処理を記述するファイル. |
dependencies.py | file | テスト時の依存性の上書きを定義する関数を記述するファイル. |
>>1層目のディレクトリ構成に戻る
>>2層目のディレクトリ構成に戻る
3層目のディレクトリ構成
次に、3層目のディレクトリ構成のうち解説が必要なものだけを抜粋して説明する.
databaseディレクトリ
databaseディレクトリ内では、DB作成に必要なファイルや各種seedingに関するディレクトリ/ファイルを定義している.
databaseディレクトリ内部のディレクトリ構成は以下の通り.
app-backend/
└ src/
└ database/
├ seedings/
├ __init__.py
├ database.py
├ db_handler.py
└ data_handler.py
名称 | type | 詳細 |
---|---|---|
seedings | directory | 作成したDBにseedingを行う処理を記述したファイル. 対象のテーブルごとにファイル分けした方が分かりやすい. |
database | file | DBのengineやセッションの作成を行うファイル. |
table_handler | file | DBのテーブル自体の生成/削除を行うためのファイル. |
data_handler | file | 必要なデータやサンプルデータ等のInsert/Deleteを行うためのファイル. |
何が便利なのか?
このディレクトリ構成は、アプリケーションのソースコードが肥大化してきたあたりから一気に効力を発揮する.自分が今触りたい処理はどこに記述してあるのかがディレクトリを辿っていくことですぐに行きつけるからである.
また、1ファイル当たりの記述量が少なくなったり、関係ない処理同士が同一ファイル内に存在しづらくなるなど、リファクタリングなどのメンテナンス性が高いという特徴もある.
まとめ
詳説が必要なディレクトリに関してここまで解説してきたが、ファイル内の実際の記述内容や各ファイルの繋がりまでは記載しきれなかったため、実際にFastAPIでの開発経験がある人以外には便利さがなかなか伝わりづらかったかと思う.
もし今後FastAPIでのアプリケーション開発をしてみたいという初学者の方は、今回紹介したこのディレクトリ構成を用いて簡単なアプリケーションを作成する手順を示した記事を書いているので、そちらも読みながらぜひ開発への第一歩を踏み出してほしい.
Discussion