FastAPIで作るREST API入門:Pythonで高速なAPI開発を始めよう

FastAPIで作るREST API入門:Pythonで高速なAPI開発を始めよう | mohablog

FastAPIは、Pythonで高速で現代的なREST APIを構築するためのフレームワークです。本記事では、FastAPIの基礎から実装まで、初心者でもわかりやすく解説していきますね。Djangoなどの重いフレームワークではなく、シンプルで高性能なAPI開発を始めたい方は必見です。

目次

FastAPIとは

FastAPIは、Starlette(ウェブフレームワーク)とPydantic(データ検証ライブラリ)をベースにした、2018年に登場した比較的新しいフレームワークだと思います。以下のような特徴があります:

  • 高速:Node.jsやGoと同等のパフォーマンスを実現してくれます
  • 簡単:シンプルで直感的な記法で素早く開発可能です
  • 自動ドキュメント生成:SwaggerUIやReDocで自動的にAPI仕様書を作成
  • 型ヒント対応:Python 3.6+の型注釈を活用した安全なコードが書けます
  • 非同期対応:async/awaitでスケーラブルなAPI構築が可能

環境構築と基本インストール

まず、FastAPIをインストールしましょう。pipコマンドで簡単にセットアップできます:

pip install fastapi uvicorn

uvicornはASGIサーバーで、FastAPIアプリケーションを実行するために必要だと思います。その他の推奨パッケージもインストールしておくと良いですね:

pip install python-multipart pydantic

最初のFastAPIアプリケーション

では、シンプルなREST APIを作成してみましょう。以下は「Hello World」レベルのサンプルコードですが、ここから実際のプロジェクトへの応用が見えてくると思います:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello, FastAPI!"}

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

このコードをmain.pyという名前で保存し、以下のコマンドで実行します:

uvicorn main:app --reload

ブラウザでhttp://127.0.0.1:8000にアクセスすると、APIが動作しているのを確認できます。--reloadオプションを付けると、ファイル変更時に自動的に再起動されるため、開発効率がグンと向上しますね。

リクエストボディとPydanticモデル

実践的なAPIには、クライアントからのリクエストボディの処理が欠かせません。FastAPIではPydanticを使ってデータ検証を行います。最初、僕がハマったのはここで、JSONデータをどう型安全に扱うかということなんです:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    description: str = None
    tax: float = None

@app.post("/items/")
async def create_item(item: Item):
    return item

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_id": item_id, "item": item}

ItemというPydanticモデルを定義することで、自動的に以下の処理が実行されるようになります:

  • リクエストボディのJSON形式をItemインスタンスに変換
  • 型チェック(例:priceは必ずfloat型である必要がある)
  • 必須項目と任意項目の区別(=Noneで任意になります)
  • 自動的にSwaggerドキュメントに反映される

自動ドキュメント生成

FastAPIの最大の特徴の一つが、自動的にAPI仕様書を生成する機能です。アプリケーション実行中に以下のURLにアクセスしてみてください:

  • http://127.0.0.1:8000/docs – Swagger UIでインタラクティブなドキュメント
  • http://127.0.0.1:8000/redoc – ReDocで読みやすいドキュメント

これらのドキュメントは、コード内の型注釈とdocstringから自動生成されます。追加の設定を記述する必要がなく、コード自体がドキュメントになるというのは、開発効率を大きく向上させるんですよね。

クエリパラメータとパスパラメータ

REST APIでは、URLからのデータ取得パターンが複数あります。それぞれを実装してみましょう。現場ではこれらの使い分けが実は地味に重要です:

from fastapi import FastAPI
from typing import Optional

app = FastAPI()

# パスパラメータ
@app.get("/users/{user_id}")
async def get_user(user_id: int):
    return {"user_id": user_id}

# クエリパラメータ
@app.get("/search/")
async def search(q: str, skip: int = 0, limit: int = 10):
    return {"query": q, "skip": skip, "limit": limit}

# 複合パラメータ
@app.get("/products/{category}/")
async def get_products(category: str, skip: int = 0, limit: int = 20, on_sale: Optional[bool] = None):
    return {
        "category": category,
        "skip": skip,
        "limit": limit,
        "on_sale": on_sale
    }

on_sale=Noneとすることで、パラメータはオプショナルになります。型注釈により、自動的に型チェックが行われるため、バグを未然に防げるんです。

HTTPメソッドとステータスコード

REST APIでは、適切なHTTPメソッドとステータスコードの使い分けが重要です。調べてみたら、FastAPIでは本当に簡単に実装できることに驚きました:

from fastapi import FastAPI, status
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float

# GET - リソース取得
@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id, "name": "Sample Item"}

# POST - リソース作成
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(item: Item):
    return {"message": "Item created", "item": item}

# PUT - リソース更新(置換)
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_id": item_id, "item": item}

# DELETE - リソース削除
@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(item_id: int):
    return None

status_codeパラメータで、レスポンスのHTTPステータスコードを指定できます。201 Created204 No Contentなど、RESTful APIの慣例に従った実装が可能だと思います。

エラーハンドリング

堅牢なAPIには、適切なエラーハンドリングが必須です。FastAPIではHTTPExceptionを使ってシンプルに実装できるんですね:

from fastapi import FastAPI, HTTPException

app = FastAPI()

# ダミーデータベース
items_db = {
    1: {"id": 1, "name": "Item 1"},
    2: {"id": 2, "name": "Item 2"}
}

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(
            status_code=404,
            detail="Item not found"
        )
    return items_db[item_id]

@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(
            status_code=404,
            detail="Item not found"
        )
    del items_db[item_id]
    return {"message": "Item deleted"}

HTTPExceptionを発生させると、FastAPIが自動的に適切なエラーレスポンスをJSON形式で返してくれます。公式ドキュメントによると、これによって一貫性のあるエラー処理が実現できるんです。

非同期処理の活用

FastAPIは非同期処理に対応しており、async/awaitを使うことでスケーラブルなAPIを構築できます。本番環境での処理速度が大きく変わる部分ですね:

import asyncio
from fastapi import FastAPI

app = FastAPI()

@app.get("/slow-item/{item_id}")
async def read_slow_item(item_id: int):
    # 外部APIの呼び出しなど、時間がかかる処理をシミュレート
    await asyncio.sleep(2)
    return {"item_id": item_id, "processed": True}

@app.get("/fast-items/")
async def read_fast_items():
    # 複数の非同期操作を並列実行
    results = await asyncio.gather(
        asyncio.sleep(1),
        asyncio.sleep(1)
    )
    return {"message": "All items fetched", "time": "~1 second"}

非同期処理により、複数のリクエストを効率的に処理でき、APIのパフォーマンスが大幅に向上します。

CORSの設定

ブラウザからのクロスオリジンリクエストに対応する場合、CORS(Cross-Origin Resource Sharing)の設定が必要になります。最初、ここでハマった経験があります:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 本番環境では具体的なドメインを指定
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/items/")
async def read_items():
    return [{"id": 1, "name": "Item 1"}]

allow_origins["*"]を指定すると全て許可されますが、セキュリティ上、本番環境では具体的なドメインを指定する必要があります。開発段階では便利ですが、運用時には気をつけましょう。

まとめ

FastAPIを使うことで、Pythonで高速で現代的なREST APIを簡単に構築できるんですね。主なポイントは以下の通りです:

  • セットアップが簡単:FastAPIとuvicornをインストールするだけで開始可能
  • 型ヒント対応:Python 3.6+の型注釈で自動的に検証とドキュメント生成
  • 自動ドキュメント生成:Swagger UIとReDocで/docsと/redocにアクセス
  • Pydanticモデル:リクエストボディの検証と変換が自動的に実行される
  • 非同期対応:async/awaitでスケーラブルなAPI開発が可能
  • エラーハンドリング:HTTPExceptionで簡潔にエラー処理を実装
  • CORS対応:ミドルウェアで容易にクロスオリジン設定が可能

FastAPIは学習曲線が緩く、同時に本番環境で使用可能な高性能なフレームワークだと思います。今からPythonでREST API開発を始める方に、強くお勧めします。

よくある質問(FAQ)

FastAPIはDjangoと比べてどう違うのですか?

FastAPIはAPI開発に特化した軽量フレームワークで、Django(フルスタックフレームワーク)とは設計思想が異なります。FastAPIの方がAPI開発の開発速度が速く、パフォーマンスも優れていますね。DjangoはテンプレートエンジンやAdmin画面など、Web全般に対応しているため、より大規模なプロジェクト向けと言えます。

非同期処理(async/await)は必須ですか?

必須ではありませんが、推奨されています。非同期処理を使うことで、I/O待機中に他のリクエストを処理できるため、スケーラビリティが向上します。同期的な関数でも動作しますが、本番環境ではasync/awaitの使用が現場での標準になってきていると思います。

PydanticモデルなしでAPI開発できますか?

技術的には可能ですが、Pydanticを使わないことは強く非推奨です。Pydanticを使うことで、型チェック、自動ドキュメント生成、バリデーションなどが自動的に実現されます。調べてみたら、これらの機能を手動で実装すると、かなりの手間と複雑さが増すことがわかりました。

本番環境でのデプロイはどう行うのですか?

FastAPIアプリケーションはuvicornで実行されますが、本番環境ではGunicornやNginxとの組み合わせが一般的です。公式ドキュメントによると、Dockerコンテナ化して、クラウドプラットフォーム(AWS、GCP、Heroku等)にデプロイするのが標準的なアプローチになっています。

データベースはどう接続するのですか?

FastAPI自体はデータベース機能を持たないため、SQLAlchemy、Tortoise ORM、Mongoengineなどのライブラリを別途使用します。SQLAlchemyはSQL系データベース、Tortoise ORMは非同期対応が特徴です。どのORMを選ぶかは、プロジェクトの要件によって判断することになりますね。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次