2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FastAPIとuvで始めるPythonモダンAPI開発

Posted at

はじめに

Python 製の Web API フレームワークである FastAPI をご存じでしょうか。
近年、FastAPI はさまざまなサービスで活用されており、その使いやすさや性能が注目されています。
私自身も学習を兼ねて、どのようなフレームワークなのか体験してみたいと思いました。

また、Python のパッケージマネージャとして話題になっていた uv も併せて導入してみて、
FastAPI + uv + 認証 + Pydantic バリデーション + pytest によるテストという構成で簡単な API を構築してみました。

今回作成したものこちら

FastAPI とは?

FastAPI は Python 製の Web フレームワークの一つで、以下のような特徴があります。

  • 型ヒントを活用した 自動バリデーション
  • OpenAPI(Swagger)仕様に準拠したドキュメント自動生成
  • async/await による 非同期処理への対応
  • Pydantic による データモデル定義の簡素化

近年では、FastAPI は Python の Web API 開発におけるデファクトスタンダードの一つとなりつつあります。
その人気は GitHub のスター数にも表れており、2025 年 6 月時点での主要フレームワークのスター数は以下の通りです。

FastAPI (fastapi/fastapi) → 86,400 スター
Flask (pallets/flask) → 69,800 スター

FastAPI は 2018 年 12 月に最初のリリースが行われて以降、わずか数年で Flask を上回るスター数を獲得しています。
FastAPI が Python Web API 開発のデファクトスタンダードとなっていることが分かります。

uv とは?

uv は Python 用の超高速パッケージマネージャです。
Poetry や pip の代替として注目されており、依存関係の解決がとても速いという特徴があります。
今回は uv を使って仮想環境の作成やパッケージインストールを行ってみました。

環境構築

※ uv が未導入の方は、公式のインストールガイドを参考に導入してください。

# 初期化
uv init

# ライブラリのインストール
uv add fastapi[standard]
uv add --dev ruff pytest pytest-cov

# Windows の場合
.venv\Scripts\activate.bat
# macOS/Linux の場合
source .venv/bin/activate

ディレクトリ構成

fastapi-tutorial/
├── main.py                # FastAPIアプリ本体(エントリポイント)
├── src/
│   ├── auth.py            # 認証のロジック
│   ├── models.py          # Pydanticによるデータモデル
│   ├── router.py          # ルーティング(エンドポイント定義)
│   └── __init__.py
├── tests/
│   ├── test_auth.py       # 認証ロジックのテスト
│   ├── test_models.py     # モデルのバリデーションテスト
│   ├── test_router.py     # APIエンドポイントのテスト
│   └── __init__.py
├── pyproject.toml
├── uv.lock
├── README.md
└── ...
  • main.pysrc/router.py を FastAPI アプリに組み込む構成です
  • 認証・モデル・ルーティングは src/ ディレクトリに分離しています
  • テストは tests/ ディレクトリにまとめています

テスト

今回は実運用も見据えてテストコードを作成しました。

  • ルートエンドポイントの正常系/異常系
  • /items/{item_id} の認証・バリデーション・クエリパラメータ
  • /items POST のバリデーション(必須/型/値域/異常系)
  • 認証(有効/無効/スキーム不正/トークンなし等)
  • モデルのバリデーション(Pydantic)
  • エラーハンドリング(404, 405, 422 など)

実装

auth.py

FastAPI の Depends を活用して、ベアラー形式の認証を担うモジュールです。
今回は JWT の内容を本格的に検証するというよりも、構文チェックとモック検証の形で実装しています。

auth.py
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

security = HTTPBearer()

def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
    token = credentials.credentials
    if token != "mocked-jwt-token":
        raise HTTPException(status_code=401, detail="Invalid token")
    return token
  • security = HTTPBearer() でベアラー認証の仕組みを用意し、verify_token関数でトークンの検証を行います
  • 今回は「mocked-jwt-token」という文字列のみを有効なトークンとしています

models.py

Pydantic を使ったデータモデル定義です。

models.py
from pydantic import BaseModel, Field

class Item(BaseModel):
    name: str = Field(..., min_length=1)
    price: float = Field(..., gt=0)

class ItemResponse(BaseModel):
    item_id: int
    name: str
    price: float
    q: str | None = None
  • Itemはリクエストボディ用、ItemResponseは API レスポンス用のモデルです
  • バリデーション(例:name は 1 文字以上、price は 0 より大きい)も Pydantic で簡潔に記述できます

router.py

FastAPI アプリのルーティング(エンドポイント定義)をまとめたファイルです。

router.py
from fastapi import APIRouter, Depends, Path, Query
from .auth import verify_token
from .models import Item, ItemResponse

router = APIRouter()

@router.get("/")
async def read_root():
    return {"message": "Welcome to the FastAPI application!"}

@router.get("/items/{item_id}", response_model=ItemResponse)
async def read_item(
    item_id: int = Path(..., gt=0),
    q: str | None = Query(None, max_length=50),
    _: str = Depends(verify_token),
):
    item = {"name": f"item{item_id}", "price": 100.0}
    return ItemResponse(item_id=item_id, name=item["name"], price=item["price"], q=q)

@router.post("/items", response_model=ItemResponse)
async def create_item(item: Item, _: str = Depends(verify_token)):
    return ItemResponse(item_id=1, name=item.name, price=item.price)
  • /items/{item_id} でアイテム取得、/items でアイテム作成ができます
  • どちらも認証(ベアラートークン)が必要です
  • レスポンス型やバリデーションも自動で行われます

サーバーの起動方法

FastAPI アプリの開発サーバーは、公式ガイドに従い以下のコマンドで起動できます。

uv run fastapi dev

このコマンドは依存関係の解決・仮想環境の作成・開発サーバーの起動を一括で行います。
本番環境では、以下のコマンドを使用します。

uv run fastapi run

FastAPI CLI の詳細は公式ドキュメントを参照してください。

API ドキュメントの確認

サーバー起動後、以下の URL にアクセスすると自動生成された API ドキュメント(Swagger UI)を確認できます。

http://localhost:8000/docs (Swagger UI)
http://localhost:8000/redoc (ReDoc)

動作確認

では、実際に作成したものを動作確認してみます。
今回は Swagger UI で動作確認します。

正常系

image.png

不正なトークン

image.png

不正なボディ

image.png

存在しない ID

image.png

pytest によるテスト

ここでは tests/test_router.py で定義したエンドポイントの動作確認のテストを抜粋して紹介します。

test_router.py
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_root_endpoint_success():
    """ルートエンドポイントが正常に動作することを確認"""
    response = client.get("/")
    assert response.status_code == 200
    data = response.json()
    assert data["message"] == "Welcome to the FastAPI application!"


def test_get_item_with_valid_token():
    """有効なトークンでアイテム取得が正常に動作することを確認"""
    headers = {"Authorization": "Bearer mocked-jwt-token"}
    response = client.get("/items/1", headers=headers)
    assert response.status_code == 200
    data = response.json()
    assert data["item_id"] == 1
    assert data["name"] == "item1"
    assert data["price"] == 100.0
    assert data["q"] is None

def test_create_item_with_valid_token_and_data():
    """有効なトークンと正しいデータでアイテム作成が正常に動作することを確認"""
    headers = {"Authorization": "Bearer mocked-jwt-token"}
    payload = {"name": "test item", "price": 50.0}
    response = client.post("/items", json=payload, headers=headers)
    assert response.status_code == 200
    data = response.json()
    assert data["item_id"] == 1
    assert data["name"] == "test item"
    assert data["price"] == 50.0
    assert data["q"] is None
  • ルートエンドポイントの正常系
  • /items/{item_id} の認証・バリデーション
  • /items POST のバリデーション

テスト実行:

uv run pytest

まとめ

今回、FastAPI でのAPI開発からuv を活用した環境構築・認証・バリデーション・pytest テストという一連を試してみました。

  • uv による爆速環境構築
  • FastAPI の DI やバリデーションのシンプルさ
  • テストのしやすさ(TestClient が便利)

これらの点が魅力的に感じました。

今回はまだ本格的な JWT 検証や DB 連携は行っていませんが、次はSQLModel や DB 連携、OAuth2 認証にも挑戦してみたいと思いました。

参考資料

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?