FastAPIを使ってAPIをつくる(初学者向け・概念の理解)
この記事ではFastAPIを使ってAPIをつくる方法について説明します。
初学者向けで、概念の説明中心ですのであらかじめご了承ください。
※「API基礎(初学者向け)」を踏まえた内容になっております。
1. FastAPIとは?
APIを作るためのPythonフレームワーク(ツール) です。
- API = アプリ同士のやりとりの仕組み(概念)
- FastAPI = PythonでAPIを簡単に作るための「道具」
特徴
- 型ヒント対応:Pythonの型アノテーションを使って入力・出力を自動で検証
- 自動ドキュメント生成:Swagger UI / ReDoc が標準で付属し、チーム内でのAPI仕様共有が容易
- 高性能:非同期処理(async/await)をサポート。Uvicorn/StarletteベースでDjangoやFlaskより高速
- 学習コストが低い:シンプルな記法で書き始められる
他のフレームワークとの違い
-
Django:
管理画面・認証・権限・ORM・テンプレート・フォーム・マイグレーションが同梱(全部入り)で、設定すれば一式そろう。サーバーサイドレンダリングや大規模Webアプリに強いが、API専用に使うとやや重厚 -
Flask:
最小限で始まり、必要なものを拡張で足す設計。小規模APIや試作を最短で立ち上げやすい。自由度が高い反面、設計指針がなくチーム開発では統一方針を明確にする必要あり。 -
FastAPI:
型安全かつ、自動ドキュメントで仕様がコードと常に同期して共有しやすい。非同期I/Oに対応しているので高速。
2. 実際の設計要素
エンドポイント
クライアントが特定の機能やデータにアクセスするための入り口。
まずは、main.pyで最初のエンドポイント(APIの入り口)を作ります。
ディレクトリ構成例:
app/
main.py ← アプリの起動やルーター(次項で説明)の読み込みを行う
<main.pyの役割>
- FastAPI() を初期化する
- app.include_router() でルーターを読み込む
ルーター(エンドポイントの束)
エンドポイントが増えてきたら、ルーターに分割して管理します。
ディレクトリ構成例:
app/
api/ ← APIルーター
__init__.py ← Pythonのディレクトリをパッケージとして認識させるためのファイル
main.py
users.py ← 例:ユーザー関連のエンドポイント
</apiディレクトリの役割>
- エンドポイントを機能ごとに分割・集約(例:認証関連 →
auth.py
、ユーザー関連 →users.py
) - ルーターがあることで、main.pyはエンドポイント全体の管理に集中することができます。
スキーマ定義(入力・出力の型)
Pythonは動的型付け言語[1]なので、型が曖昧だとバグの原因になります。
FastAPIは Pydantic[2] を用いて入力・出力を自動バリデーションします。
ディレクトリ構成例:
app/
main.py
api/
__init__.py
users.py
schemas.py ← リクエスト/レスポンス用の型(Pydanticモデル)
<schema.pyの役割>
例:クライアントから「新しいユーザーを作って」というリクエストと一緒にデータが送られるとします。このとき FastAPI では schemas.py にクラスを作って、「nameは文字列」「emailは文字列で必須」とルールを定義できます。もし email が空だったり、数値が送られてきたら、FastAPIが自動でエラーを返します。
ユーザーリクエスト例:
{
"name": "Mio",
"email": "mio@example.com"
}
DBモデル定義(SQLAlchemy)
SQLAlchemyのORM[3]を使うと「Pythonクラス=DBテーブル」として扱えます。
ディレクトリ構成例:
app/
main.py
api/
__init__.py
users.py
models.py ← データベースのテーブル定義(SQLAlchemyモデル)
schemas.py
<model.pyの役割>
- 「DBにどんなテーブルがあるか」、「カラムは何か、型は何か」、「Userはid・name・emailを持つ」などのデータ構造を表現する。
- 注意点:
- 業務ルールやビジネスロジックは書かない
- DBアクセスの操作手順(CRUDロジック)は原則ここに書かない
- セッションのスコープ管理を徹底すること。グローバルセッションを持つと「セッションリーク」「トランザクション競合」の原因になるので、
Depends(get_db)
でリクエストごとにセッションを管理すること。
サービス層(ビジネスロジック)
アプリケーションのビジネスロジック(業務ルールや処理手順)をまとめる層。
ルーターとDB操作(モデル/リポジトリ)の 中間に位置する橋渡し役 です。
ディレクトリ構成例:
app/
main.py
api/
__init__.py
users.py
models.py
schemas.py
services/
user_service.py ← 業務ロジックを集約
フロー図:
[ルーター] → [サービス層] → [モデル] → [DB]
<サービス層の役割>
ルーターに直接DB操作を書くと、処理が複雑になりやすく再利用もしにくいです。
- ルーターの責務を減らす
→ルーターは「HTTPリクエストを受け取る→サービスを呼ぶ」だけにする - 業務ルールを集約
→「未払い請求があれば削除不可」「パスワードはハッシュ化して保存」などをここに書く - テストしやすくする
→サービス層だけを単体テストすれば、DBやHTTPを立てなくても動作確認できる
設定・環境変数管理
チーム開発では、ローカル・本番・CIなど環境ごとにDBやAPIキーが異なります。
.env ファイル+config.py で管理するのがベストプラクティスです。
これにより、チームごとに「開発環境」「本番環境」が違っても、コードを変えずに環境を切り替えられます。
ディレクトリ構成例:
app/
main.py
api/
__init__.py
users.py
models.py
schemas.py
services/
user_service.py
core/
config.py ← DB URL, JWTシークレットキーなど環境変数の管理
db.py ← DB接続処理
pytestでユニットテスト/E2Eテスト
FastAPIはTestClientを用いて簡単にAPIテストを書けます(Swaggerで試すだけだと壊れても気づけない。)。
CIで自動テストを回すことで、安心してリファクタリングできます。
ディレクトリ構成例:
app/
main.py
api/
__init__.py
users.py
models.py
schemas.py
services/
user_service.py
core/
config.py
db.py
tests/
まとめ
- エンドポイント:APIの入り口(クライアントからの要求を受け付ける)
- ルーター:エンドポイントを束ねる(責務を整理し、main.pyをスリムに保つ)
- スキーマ:入出力の型定義(pydanticで自動バリデーション)
- モデル:DBのテーブル定義(SQLAlchemyで安全にCRUD)
- サービス層:ビジネスロジックを集約(ルーターを薄く、再利用性を高める)
- config/core:環境変数と設定を一元管理(本番と開発でコード変更不要)
- テスト:pytest+CI/CDで自動検証(壊れない仕組みづくり)
使う時は以下のような工夫が必要:
- ルーターが肥大化するとレビュー困難&バグ温床 → ルーター薄く+サービス層/リポジトリで責務分離
- 入出力の型が曖昧だと仕様ズレ → Pydantic で入出力スキーマ固定
- 秘密情報をコード直書きすると事故る → .env + config.py で設定を外出し
- 手動テストだけだとリグレッション[4]に気づけない → pytest + TestClient をCIで回す
FastAPIは「書きやすい」だけでなく、設計やルールを工夫すれば安心してチーム開発できるAPIフレームワークです。
-
動的型付け:変数を宣言するときに型を決めなくてもよく、実行時に型が決まる ↩︎
-
Pydanticは、Pythonの「型ヒント」を実行時にチェックしてくれるライブラリです。BaseModel クラスを継承して属性を定義します。 ↩︎
-
プログラミングの上で、オブジェクト指向プログラミング(以下、OOP)とリレーショナルデータベースの連携を実現するプログラミング技法です。ORMを使用することで、データベースの操作を書く際にSQLを直接記述せずに、プログラム言語のオブジェクトを使用して操作を実現できます。参考記事: Qiita ORMとは ↩︎
-
新しい機能追加や修正をした結果、以前は正常に動いていた機能が壊れてしまうこと。 ↩︎
Discussion