ChatGPT先生と挑むFastAPI #1|FastAPI入門と最初のAPI

記事内に広告が含まれています。
タイトル

STEP1では、そもそもFastAPIとは何かを説明してもらい、そのあとに開発環境を構築してから最初のAPIを作成します。FastAPIでAPIを作ると、APIドキュメントが自動生成されます。このドキュメントをSeagger UIで確認します。

ChatGPT先生
ChatGPT先生

それではSTEP1を始めましょう!

■■■スポンサーリンク■■■

今回学ぶこと

今回のステップで学ぶ内容を一覧で出してもらいました。

ChatGPT先生
ChatGPT先生

STEP1では以下の内容を学習します。

  1. FastAPIとは何かを理解する
  2. Docker / Dev Containersで開発環境を構築する
  3. 最初のGET APIを作る
  4. FastAPIアプリを起動して動作確認する
  5. Swagger UIを確認する
  6. 自力課題

学習開始

それでは学習をはじめます。

FastAPIとは何かを理解する

FastAPIとは?

ChatGPT先生
ChatGPT先生

FastAPIは、Pythonで Web APIを作るためのWebフレームワーク です。
クライアントからHTTPリクエストを受け取り、Pythonで処理を行い、その結果をHTTPレスポンスとして返す役割を担います。

処理の流れは以下のようなイメージになります。

クライアント
↓
HTTPリクエスト
↓
FastAPI
↓
Pythonの処理
↓
HTTPレスポンス
↓
クライアント

FastAPIを使わずにHTTP通信をPythonだけで一から処理しようとすると、以下のような多くの処理を自分で用意する必要があります。

  • URLを判定する
  • GETやPOSTを判定する
  • パラメータを取得する
  • JSONを読み取る
  • 入力値をチェックする
  • JSONレスポンスを作る
  • HTTPステータスコードを設定する

FastAPIは、このようなWeb API開発でよく必要になる処理をフレームワークとして提供してくれます。

そのため、開発者は「このURLにアクセスされたらこの処理を実行してデータを返す」というアプリケーション本来の処理に注力しやすくなります。

FastAPIの大きな特徴

ChatGPT先生
ChatGPT先生

STEP 1の段階では、まず次の3つを押さえておけば十分です。

① Pythonの型ヒントを活用する

例えば、次のようなPythonの型情報を、FastAPIがAPIの入力チェックなどにも利用します。

name: str
age: int

② APIドキュメントを自動生成できる

FastAPIでAPIを作ると、Swagger UIの画面から「どんなAPIがあるのか・どんな値を渡すのか・どんな結果が返るのか」を確認できます。

③ 少ないコードでAPIを作れる

最初のAPIは、かなり短いPythonコードで作れます。このあと実際に作ってどのくらいシンプルなのか確認します。

FastAPIの立ち位置

ChatGPT先生
ChatGPT先生

今回の構成をものすごく単純化すると次のようになります。

ブラウザ・フロントエンド・他システム
↓
HTTP
↓
FastAPI
↓
Python
↓
DBなどの外部システム

FastAPIは主に外部からHTTPリクエストを受け付けて、Pythonの処理につなぐ入口を担当すると考えると分かりやすいです。

Django REST Frameworkとの違い

実際に使用したことのあるDjango REST Framework(DRF)との違いについても聞いてみました。

ChatGPT先生
ChatGPT先生

一言でまとめると、
DRFは「Djangoという大きなWebフレームワークの上で、APIを作るための仕組み」
FastAPIは「APIを作ることを中心に設計された、モダンで軽量なフレームワーク」

まず全体像を比較すると以下のような感じです。

観点FastAPIDjango REST Framework
ベースStarlette + PydanticDjango
主目的API開発DjangoでAPI開発
設計思想APIファースト、型ヒント重視Djangoの機能を活用したWeb/API開発
コード量比較的少ないやや多め
学習コスト比較的低いDjangoの知識も必要
型ヒント非常に重要必須ではない
入力検証PydanticSerializer
ORM自由に選択可能Django ORMとの相性が非常に良い
管理画面標準ではないDjango Adminが強力
認証・ユーザー管理自分で構成することが多いDjangoの認証基盤が充実
APIドキュメントOpenAPI / Swagger UIを自動生成構成次第。Browsable APIが特徴
非同期処理得意対応しているがFastAPIほど中心ではない

FastAPIは標準Pythonの型ヒントを中心に設計されており、OpenAPIやSwagger UIも標準的に自動生成されます。
DRFはDjango上で動き、Serializer、認証、パーミッション、Browsable APIなどを組み合わせてAPIを構築します。

ChatGPT先生
ChatGPT先生

一番大きな違いは「Djangoを背負っているか」

DRFは単体のフレームワークではありません。DjangoでWebアプリを作っていて、その機能をAPIとして公開したいという状況に非常に強いです。

Django
 ├─ ORM
 ├─ 認証
 ├─ Admin
 ├─ URL Routing
 ├─ Middleware
 └─ Django REST Framework
      ├─ Serializer
      ├─ APIView
      ├─ ViewSet
      └─ API用認証など

一方FastAPIは以下のような感じです。特定のデータベースやフロントエンドに依存せず統合できる設計になっています。

FastAPI
 ├─ Routing
 ├─ Validation
 ├─ Dependency Injection
 ├─ OpenAPI
 └─ Swagger UI

DB
 ↓
SQLAlchemyなどを自由に選ぶ
ChatGPT先生
ChatGPT先生

比較しやすいように、メリット・デメリットを並べるとこんな感じです。

フレームワークメリットデメリット
FastAPI・少ないコードでAPIを作りやすい
・Pythonの型ヒントをそのまま活用できる
・Pydanticによる入力値チェックが強力
・Swagger UI / OpenAPIドキュメントを自動生成できる
・async / awaitを使った非同期処理と相性が良い
・AI、機械学習、データ処理系のAPIと相性が良い
・DBや認証方式などを比較的自由に選べる
・Djangoのような管理画面が標準ではない
・ORMが標準で決められていないため、自分で選択する必要がある
・認証、ユーザー管理などを自分で構成する場面が多い
・自由度が高い分、プロジェクト構成やライブラリ選定に設計判断が必要
DRF・Djangoの豊富な機能をそのまま利用できる
・Django ORMが強力
・Django Adminで管理画面を作りやすい
・認証、ユーザー管理、権限管理が充実している
・Serializerによるデータ変換・入力チェックが充実
・大規模な業務システムやデータモデルが多いシステムと相性が良い
・Djangoの成熟したエコシステムを利用できる
・Django自体の知識も必要になる
・APIだけ作りたい場合にはやや大掛かり
・覚える概念が多い
・FastAPIと比べるとコード量が増えやすい
・非同期APIを中心に設計する場合はFastAPIほど自然ではない
ChatGPT先生
ChatGPT先生

用途も一緒に覚えるなら、かなり単純化してこう考えると分かりやすいです。

こんな場合向いている方
AI・LLM用のAPIを作りたいFastAPI
機械学習モデルをAPI化したいFastAPI
小〜中規模のAPIをシンプルに作りたいFastAPI
マイクロサービスを作りたいFastAPI
React / Next.jsのバックエンドAPIを作りたいFastAPI
会員・商品・注文などの業務システムを作りたいDRF
管理画面を簡単に用意したいDRF
認証・ユーザー・権限管理が重要DRF
Djangoで既にシステムを作っているDRF
多数のDBテーブルを扱うWebシステムDRF
ChatGPT先生
ChatGPT先生

実務でどっちのフレームワークを使用するかを判断する場合、以下のような基準で考えるとわかりやすいです。もちろん絶対ではありません。

APIそのものが主役 → FastAPI
Webシステム全体が主役 → Django + DRF

あるいは

AI・ML・データ処理 → FastAPI寄り
会員・商品・注文・管理画面 → DRF寄り

Docker / Dev Containersで開発環境を構築する

ChatGPT先生
ChatGPT先生

今回は構成は以下のようになります。

Windows 11
↓
Docker Desktop
↓
Dev Container
↓
Linux環境
↓
Python
↓
FastAPI

VS Code自体はWindows側で動きますが、PythonやFastAPIはDev Containerの中で動かします。
つまり、Windowsへ直接ツールやライブラリをインストールするのではなく、プロジェクト専用のLinux環境をDockerで用意します。

DockerとDev Containersの役割の違い

ChatGPT先生
ChatGPT先生

ここは最初に区別しておきましょう。

Dockerは、アプリケーションを実行するための隔離された環境(Container)を作る仕組みです。
例えば今回なら以下のようなライブラリが入った専用の環境を作れます。

  • Python 3.x
  • FastAPI
  • uvicorn
  • その他ライブラリ

Dev Containersは、Docker ContainerをVS Codeの開発環境として使いやすくする仕組みです。
DockerだけでもContainerは作れますが、Dev Containersを使うことで開発が簡単になります。

VS Code
↓
Dev Containerへ接続
↓
コンテナ内のPythonを使う
↓
コンテナ内でターミナルを実行

ChatGPT先生
ChatGPT先生

今回Dev Containersを使う大きな理由は、開発環境をプロジェクトごとに再現できるからです。

PCに直接Pythonを入れていると、以下のように環境が混ざりやすく管理が面倒です。

プロジェクトA
Python 3.11

プロジェクトB
Python 3.13

プロジェクトC
違うライブラリバージョン

Dev Containerなら以下のように分離できます。

FastAPI学習プロジェクト
↓
このプロジェクト専用Container
↓
Pythonやライブラリも専用

そして.devcontainer/に環境設定を残しておけば、同じ構成を作り直せます。これは実務でもかなり大きなメリットです。

開発環境を構築

Docker DesktopやVS Codeなどのツールはインストール済みとして進めます。

ChatGPT先生
ChatGPT先生

まずはrequirements.txtをプロジェクト直下に作成してください。
中身は次のようにします。

// 現時点でのディレクトリ構成
fastapi-learning/
└─ requirements.txt     ← 追加

requirements.txtの中身↓

fastapi[standard]
sqlalchemy
alembic
psycopg[binary]
pydantic-settings
pytest
pytest-asyncio
httpx
ruff
ChatGPT先生
ChatGPT先生

すぐには使用しませんが、今回の学習で必要となるライブラリはすべてインストールしておきます。各ライブラリの役割は次の通りです。

ライブラリ用途
fastapi[standard]FastAPI本体、Uvicornなど
sqlalchemyORM
alembicDBマイグレーション
psycopg[binary]PostgreSQL接続
pydantic-settings環境変数・設定管理
pytestテスト
pytest-asyncioasync処理のテスト
httpxAPIテストなどのHTTPクライアント
ruffLint / Format

※fastapi[standard] を入れると FastAPI本体に加えて、UvicornやCLI、httpx、python-multipart など標準的に使う依存関係がまとめて入る構成になっています。

ChatGPT先生
ChatGPT先生

次に、VS Code + Dev Containersで使用する開発環境用Dockerfileを作成します。
プロジェクト直下に.devcontainerフォルダを作成し、その中にDockerfileを作成して次のように書きます。

// 現時点でのディレクトリ構成
fastapi-learning/
├── .devcontainer/      ← 追加
│   └── Dockerfile     ← 追加
└── requirements.txt

Dockerfileの中身↓

FROM mcr.microsoft.com/devcontainers/python:3.12

WORKDIR /workspace

# Pythonライブラリをインストールする
COPY requirements.txt /tmp/requirements.txt

RUN pip install --no-cache-dir -r /tmp/requirements.txt
ChatGPT先生
ChatGPT先生

次にcompose.yamlをプロジェクト直下に作成します。
中身は次のようにします。

// 現時点でのディレクトリ構成
fastapi-learning/
├── .devcontainer/
│   └── Dockerfile
├── compose.yaml     ← 追加
└── requirements.txt

compose.yamlの中身↓

services:
  app:
    build:
      context: .
      dockerfile: .devcontainer/Dockerfile

    volumes:
      - .:/workspace

    command: sleep infinity

    env_file:
      - .env

    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:17

    restart: unless-stopped

    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

    ports:
      - "${POSTGRES_PORT}:5432"

    volumes:
      - postgres_data:/var/lib/postgresql/data

    healthcheck:
      test:
        [
          "CMD-SHELL",
          "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"
        ]
      interval: 5s
      timeout: 5s
      retries: 10

volumes:
  postgres_data:

これで以下の2サービスをComposeで管理します。

app:FastAPI開発環境
db:PostgreSQL

ChatGPT先生
ChatGPT先生

次に.devcontainer配下にdevcontainer.jsonを作成します。
中身は次のようにします。

// 現時点でのディレクトリ構成
fastapi-learning/
├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json     ← 追加
├── compose.yaml
└── requirements.txt

devcontainer.jsonの中身↓

{
  "name": "FastAPI Learning",
  "dockerComposeFile": "../compose.yaml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "runServices": [
    "db"
  ],
  "shutdownAction": "stopCompose",
  "remoteUser": "vscode",
  "forwardPorts": [
    8000
  ],

  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python",
        "charliermarsh.ruff"
      ]
    }
  }
}

この.devcontainer の設定を読み込むために、VS Codeに「Microsoft製の Dev Containers 拡張機能」をインストールしておきます。これでVS Codeが以下のような流れで開発環境を作ります。

devcontainer.json
↓
compose.yaml
↓
appコンテナへ接続 & dbコンテナ起動

ChatGPT先生
ChatGPT先生

次に.envと.env.exampleをプロジェクト直下に作ります。

// 現時点でのディレクトリ構成
fastapi-learning/
├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
├── .env              ← 追加
├── .env.example      ← 追加
├── compose.yaml
└── requirements.txt

まずは.env.exampleを作成します。このファイルは「このプロジェクトでは、こういう環境変数が必要です」ということを他の開発者へ共有するために使います。

POSTGRES_DB=fastapi_learning
POSTGRES_USER=fastapi
POSTGRES_PASSWORD=your_password
POSTGRES_PORT=5432

DATABASE_URL=postgresql+psycopg://fastapi:your_password@db:5432/fastapi_learning

次に.env.exampleをベースに.envを作成します。
※今回はローカル開発用なので単純なパスワードにしています。

POSTGRES_DB=fastapi_learning
POSTGRES_USER=fastapi
POSTGRES_PASSWORD=fastapi
POSTGRES_PORT=5432

DATABASE_URL=postgresql+psycopg://fastapi:fastapi@db:5432/fastapi_learning

.envには正式な認証情報が設定されるためGit管理の対象外とします。

一方、.env.exampleにはこのアプリを動かすために必要な環境変数と、その設定例を記載を記載してGit管理します。

ChatGPT先生
ChatGPT先生

次に.gitignoreをプロジェクト直下に作成します。

// 現時点でのディレクトリ構成
fastapi-learning/
├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
├── .env
├── .env.example
├── .gitignore      ← 追加
├── compose.yaml
└── requirements.txt

.gitignoreの中身↓

# Environment variables
.env

# Python
__pycache__/
*.py[cod]
*.pyo

# Virtual environment
.venv/
venv/

# pytest
.pytest_cache/
.coverage
htmlcov/

# Ruff
.ruff_cache/

# IDE / OS
.DS_Store
Thumbs.db
ChatGPT先生
ChatGPT先生

これで開発環境を構築するための資材一式ができました。
これから実際に開発環境を起動して確認します。

VS Codeでコマンドパレットを開いて(Ctrl + Shift + P)、検索欄にDev Containers: Reopen in Containerと入力してします。

Dev Containers: Reopen in Containerを実行すると、

compose.yaml
├─ app
└─ db

が起動して、VS Codeはappコンテナへ接続します。

ChatGPT先生
ChatGPT先生

主要ライブラリが入っていることをまとめて確認します。

python -c "import fastapi, sqlalchemy, psycopg, pydantic_settings, pytest; print('OK')"
開発環境の確認
ChatGPT先生
ChatGPT先生

このコマンドが通れば開発環境の構築は完了です。

Dev Containersで実際によく使うコマンド

開発中にDev Containersで実際によく使うコマンドを教えてもらいました。

コマンド用途使うタイミング
Dev Containers: Reopen in Container現在のフォルダをDev Containerで開く初回作成・Containerへ入りたいとき
Dev Containers: Rebuild and Reopen in ContainerContainerイメージを再ビルドして、そのContainerで開き直すDockerfile、compose.yaml、devcontainer.json などを変更したとき
Dev Containers: Reopen Folder LocallyDev Containerを抜けて、元の環境でフォルダを開き直すContainerでの作業を終了するとき
Dev Containers: Show Container LogDev Container作成・起動時のログを確認するReopen in Container がエラーになったとき
Dev Containers: Open Container Configuration File現在のDev Container設定を開くdevcontainer.json を確認・編集したいとき

最初のGET APIを作る

ChatGPT先生
ChatGPT先生

ここからは実際にコードを書いて、最初のGET APIを作っていきます。

まずプロジェクト直下に app ディレクトリを作り、その中に main.py を作成してください。

fastapi-learning/
├── .devcontainer/
├── app/
│ └── main.py      ← 追加
├── .env
├── .env.example
├── .gitignore
├── compose.yaml
└── requirements.txt

main.pyの中身↓

from fastapi import FastAPI

# FastAPIアプリケーションを作成する
app = FastAPI()


# GET / にアクセスされたときの処理を定義する
@app.get("/")
def read_root():
    return {"message": "Hello, FastAPI!"}
ChatGPT先生
ChatGPT先生

このコードを解説します。

4行目でFastAPIアプリケーションのインスタンスを作成しています。

app = FastAPI()

Djangoではプロジェクト全体の設定や urls.py などを組み合わせますが、FastAPIではまずこの app オブジェクトがAPIアプリケーションの中心になります。

そして重要なのが8行目です。これは、「HTTPのGETメソッドで / にリクエストが来たら、この下の関数を実行する」という定義です。

@app.get("/")

FastAPIではこのような、

@app.get(...)
@app.post(...)
@app.put(...)
@app.delete(...)

を Path Operation Decorator と呼びます。

今回のコードの場合はGET /のリクエストが来たら、read_root()を実行することになります。
read_root()は普通のPython関数です。

ChatGPT先生
ChatGPT先生

では、動かしてみましょう。
今回は app/main.py に作ったFastAPIアプリを、実際にASGIサーバー上で起動します。

Dev Container内のターミナルで、プロジェクト直下から次を実行してください。

実行するコマンド↓

uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

このコマンドの特に重要なのが、app.main:appの部分です。

これは、「app/main.py にある app というFastAPIアプリケーションを起動する」という意味になります。

app.main:app/main.py というPythonモジュール
:app:main.py内の app = FastAPI() というオブジェクト変数

このコマンドを実行すると以下のように動くイメージです。

uvicorn
└─ app.main:app
      ↓
   app/main.py
      ↓
   app = FastAPI()

--reload は、開発中にソースコードを変更したとき、自動的にサーバーを再起動するためのオプションです。

コマンドの実行結果は次のようになります。

実行結果

今起きている処理の流れは次ようになります。

ブラウザ
   │
   │ GET /
   ▼
localhost:8000
   │
   ▼
Uvicorn
   │
   ▼
FastAPI
   │
   ▼
@app.get("/")
   │
   ▼
read_root()
   │
   ▼
Pythonのdict
   │
   ▼
JSONレスポンス
   │
   ▼
ブラウザ

※uvicornコマンドで実行したプロセスはCtrl + Cで終了できます。

Swagger UIを確認する

ChatGPT先生
ChatGPT先生

FastAPIアプリを起動したまま、ブラウザで次へアクセスしてください。

http://localhost:8000/docs

すると、FastAPIが自動生成した Swagger UI が表示されます。

Swagger UIを表示

FastAPIでは、Pythonコードに書いた以下の内容からOpenAPI仕様を自動生成し、それをSwagger UIで表示します。

  • HTTPメソッド
  • URL
  • パラメータ
  • リクエストデータ
  • レスポンス
  • 型情報
ChatGPT先生
ChatGPT先生

ここがFastAPIのかなり便利なところです。

自力課題

課題内容

ChatGPT先生
ChatGPT先生

現在のGET /はそのまま残して、新しくGET /helloのAPIを追加してください。
このAPIへアクセスすると、次のJSONを返すようにします。

{
"message": "Hello from my first API!"
}

完了条件

ChatGPT先生
ChatGPT先生

次の3点を満たせばOKです。

  • GET /hello を自分で実装できている
  • ブラウザでhttp://localhost:8000/hello にアクセスしてJSONが返る
  • Swagger UIにも GET /hello が自動的に追加されている

実装結果

実装したコード:main.py 13行目以降

from fastapi import FastAPI

# FastAPIアプリケーションを作成する
app = FastAPI()


# GET / にアクセスされたときの処理を定義する
@app.get("/")
def read_root():
    return {"message": "Hello, FastAPI!"}


# STEP1 自力課題 GET /hello
@app.get("/hello")
def read_hello():
    return {"message": "Hello from my first API!"}

ブラウザでの表示結果

ブラウザでの表示結果

Swagger UIでの確認結果

ChatGPT先生のレビュー結果

ChatGPT先生
ChatGPT先生

問題ありません。自力課題はクリアです。

確認した限り、完了条件をすべて満たしています。

  • GET /hello が実装されている
  • ブラウザから /hello にアクセスして、指定どおりのJSONが返っている
  • Swagger UIにも GET /hello が追加されている

まとめ

STEP1で学んだことを振り返っていきます。

まずFastAPIとは何かを学びました。

FastAPIはWeb API開発用のフレームワークで、HTTP関連の処理やルーティングといったWeb API開発でよく必要となる処理を提供してくれるため、開発者はアプリケーション開発に注力しやすくなります。

DRFではDjangoの上にWeb APIが乗っかるイメージとなるため、APIだけを作りたい場合には構成が大きくなりやすいですが、FastAPIはAPIを中心に必要な機能を組み合わせて構成できるため、扱いやすそうです。

フレームワークの選定基準の一つとして、作りたいものがAPIがメインの場合はFastAPI、Djangoを使ったWebシステムにAPIを追加したい場合はDRF、のような感じで考えることができそうです。(絶対ではありませんが。)

これまでDRFしか使ったことがなく、FastAPIは名前しか知らなかったので、同じWeb API開発用のフレームワークでも用途の違いなどを知ることができてよかったです。

開発環境はcompose.yamlにFastAPIの実装や実行するためのappサービスとdbサービスをそれぞれ作成しました。

FastAPIのライブラリをインストールする際、fastapi[standard]をインストールすることで、FastAPI本体だけでなく、UvicornなどのFastAPI開発でよく使われる依存ライブラリもまとめてインストールすることができるのは便利だと感じました。

今回実装したコードはとても簡単なものでしたが、まずはFastAPIのインスタンスを生成し、そのインスタンスのPath Operation Decoratorを使って、エンドポイントとPython関数との関連付けをしているという基本を理解することできました。

FastAPIは実装内容からAPIドキュメントを自動生成してくれるのはとても便利だと感じました。

DRFを使用していたころはAPIドキュメントを生成するためにdrf-spectacularのライブラリを別途インストールしてAPIドキュメント用のコードを書いていました。仕様変更による修正漏れも多く実装内容とAPIドキュメントが一致していないことが多々あり、とても面倒で手間がかかった記憶があります。

しかし、FastAPIは実装内容からAPIドキュメントを自動生成してくれるため、仕様変更による修正漏れが起きにくそうなのと、APIドキュメントを作るための手間が少ないのはとても魅力的です。

まずは今回学んだ基本をしっかり理解して次回以降のSTEPに取り組んでいきたいと思います。

コメント

タイトルとURLをコピーしました