🐻‍❄️

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フレームワークです。

脚注
  1. 動的型付け:変数を宣言するときに型を決めなくてもよく、実行時に型が決まる ↩︎

  2. Pydanticは、Pythonの「型ヒント」を実行時にチェックしてくれるライブラリです。BaseModel クラスを継承して属性を定義します。 ↩︎

  3. プログラミングの上で、オブジェクト指向プログラミング(以下、OOP)とリレーショナルデータベースの連携を実現するプログラミング技法です。ORMを使用することで、データベースの操作を書く際にSQLを直接記述せずに、プログラム言語のオブジェクトを使用して操作を実現できます。参考記事: Qiita ORMとは ↩︎

  4. 新しい機能追加や修正をした結果、以前は正常に動いていた機能が壊れてしまうこと。 ↩︎

Discussion