FastAPI入門

このハンズオンでは、PythonのWebフレームワークであるFastAPIの概要を学び、簡単なAPIを実際にハンズオン形式で手を動かしながら体験します。

  • FastAPIの概要と特徴
  • FastAPIアプリケーションの作成と実行
  • パスパラメータとクエリパラメータ
  • リクエストボディとPydanticモデル
  • curlコマンドによるAPIの動作確認
  • 自動生成ドキュメント(Swagger UI)の活用

1. 事前準備

このハンズオンでは、以下のツールが必要です。まだ準備できていない場合は、リンク先の手順に沿って準備をお願いします。

2. FastAPIとは

FastAPIは、PythonでAPIを構築するための高性能なWebフレームワークです。Webフレームワークとは、Webアプリケーションの開発に必要な機能をまとめて提供するライブラリのことです。FastAPIには以下のような特徴があります。

  • Node.jsやGoに匹敵する高速なパフォーマンスを実現できる
  • Pythonの型ヒントを活用したリクエストの自動バリデーションが行える
  • Swagger UI/docs)によるAPIドキュメントが自動で生成される
  • Pydanticとの統合により、データの検証とシリアライズが自動で行われる

FastAPIは内部でStarlettePydanticという2つのライブラリを利用して構築されています。

📝 Starletteとは
Starletteは、Pythonの軽量なASGI Webフレームワークです。HTTPリクエストの受信やレスポンスの送信、ルーティング、ミドルウェアなど、Webアプリケーションの基盤となる機能を提供しています。FastAPIはStarletteの上に構築されており、FastAPIでルーティングやリクエスト処理を行う際、内部的にはStarletteの機能が使われています。
📝 Pydanticとは
Pydanticは、Pythonのデータバリデーション(検証)ライブラリです。クラスにフィールドの型を定義するだけで、入力データの型チェックや変換を自動で行います。FastAPIではリクエストボディやレスポンスのデータ検証にPydanticが使われており、この講座の後半でBaseModelを使ったモデル定義を体験します。
💡 ポイント
StarletteやPydanticの詳細な知識はFastAPIの利用に必須ではありませんが、より深い理解のために公式ドキュメントを参照すると役立ちます。

3. プロジェクトの準備

FastAPIは使いながら理解していくのが良いので、まずは環境の準備をしていきたいと思います。

3.1 パッケージのインストール

FastAPIと、FastAPIアプリケーションを実行するためのサーバであるuvicornをインストールします。

Windowsの場合:

pip install fastapi uvicorn

Macの場合:

pip3 install fastapi uvicorn
📝 uvicornとは
uvicornは、PythonのASGI(Asynchronous Server Gateway Interface)サーバです。FastAPIアプリケーションを実行するために必要です。開発中は--reloadオプションを使うことで、コードの変更を検知して自動的にサーバを再起動してくれます。

3.2 フォルダとファイルの作成

まず、任意の場所にfastapi-helloフォルダを作成します。

fastapi-hello/  ← このフォルダを作成

作成したフォルダをVisual Studio Codeで開きます。Visual Studio Codeのメニューから「ファイル」→「フォルダーを開く」を選択し、作成したフォルダを開いてください。

main.pyの作成

main.pyを作成します。Visual Studio Codeのエクスプローラーでfastapi-helloフォルダを右クリックし、「新しいファイル」を選択してmain.pyという名前で作成してください。

fastapi-hello/
└── main.py  ← このファイルを作成

4. FastAPIの基本

4.1 デコレータとは

FastAPIのコードを書く前に、デコレータというPythonの仕組みについて説明します。デコレータとは、関数の定義の直前に@記号を付けて記述し、その関数に追加の機能を付与する仕組みです。

@デコレータ
def 関数名():
    処理

@デコレータを関数の上に記述すると、その関数はデコレータによって追加の機能が付与されます。デコレータを使わない場合、同等の処理を実現するには関数の登録や設定を手動で書く必要がありますが、デコレータを使うことで簡潔に記述できます。

FastAPIでは、このデコレータの仕組みを使って「どのURLに対するリクエストを、どの関数で処理するか」を定義します。具体的な使い方は次のセクションで見ていきます。

4.2 ルーティングの基本

FastAPIでは、アプリケーションのインスタンスを作成し、デコレータでルーティングを定義します。ルーティングとは、リクエストのURLとHTTPメソッドに応じて、実行する関数を振り分ける仕組みです。

FastAPIにおけるリクエスト処理の流れを図に示します。

sequenceDiagram
    participant クライアント
    participant FastAPI
    participant ハンドラ関数
    クライアント->>FastAPI: HTTPリクエスト
    FastAPI->>FastAPI: ルーターがパスを照合
    FastAPI->>ハンドラ関数: 対応する関数を実行
    ハンドラ関数->>FastAPI: 戻り値を返却
    FastAPI->>クライアント: JSONレスポンス

基本的な構文は以下のとおりです。

from fastapi import FastAPI

app = FastAPI()

@app.get("/パス")
def 関数名():
    return {"キー": "値"}

FastAPI()でアプリケーションのインスタンスを作成し、@app.get()デコレータでHTTPメソッドとパスを指定します。関数が返す辞書型のデータは、自動的にJSON形式に変換されてレスポンスとして返されます。

実際に試してみましょう。作成したmain.pyに以下の内容を記述して保存します。

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
    return {"message": "Hello World"}

このコードの各部分を説明します。

FastAPI()でアプリケーションのインスタンスを作成しています。このappオブジェクトが、APIのルーティングやリクエスト処理の中心となります。

@app.get("/")はデコレータで、ルートパス(/)に対するGETリクエストを処理する関数としてroot()を登録しています。

root()関数は辞書型のデータを返しています。FastAPIでは、辞書型を返すと自動的にJSON形式に変換してレスポンスが返されます。

💡 ポイント
@app.get("/")getはHTTPメソッドのGETに対応しています。前の講座で学んだPOSTPUTDELETEに対応するデコレータとして、@app.post()@app.put()@app.delete()も用意されています。

4.3 サーバの起動

以下のコマンドでサーバを起動します。

uvicorn main:app --reload

このコマンドの各要素の意味は以下のとおりです。

要素 説明
main 実行するPythonファイル名(main.pymain
app FastAPIのインスタンス変数名
--reload コード変更時に自動でサーバを再起動する(開発用)

サーバが正常に起動すると、以下のメッセージが表示されます。

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [xxxxx] using StatReload
INFO:     Started server process [xxxxx]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
📝 ポート番号について
FastAPI(uvicorn)のデフォルトポートは8000です。ポートを変更したい場合は--portオプションで指定できます(例: uvicorn main:app --reload --port 8080)。

4.4 動作確認

別のターミナルウィンドウを開き、curlコマンドでリクエストを送信します。

curl http://localhost:8000/

以下のレスポンスが返されます。

{"message":"Hello World"}

root()関数が返した辞書型のデータが、JSON形式に変換されてレスポンスとして返されていることが確認できます。

ブラウザでhttp://localhost:8000/にアクセスしても、同じJSONレスポンスを確認できます。

📝 curlコマンドとは
curlは、ターミナルからHTTPリクエストを送信するためのコマンドラインツールです。APIの動作確認によく使用されます。引数にURLを指定するだけで、そのURLに対してGETリクエストを送信できます。

5. エンドポイントの追加

サーバは--reloadオプションで起動しているため、main.pyを変更して保存するたびにサーバが自動的に再起動されます。ここからは、さまざまな種類のエンドポイントを追加しながら、FastAPIの機能を学んでいきます。

5.1 複数のエンドポイントの定義

1つのアプリケーションに複数のエンドポイントを定義できます。main.pyに以下のエンドポイントを追加します。

@app.get("/about")
def about():
    return {"app_name": "FastAPI Demo", "version": "1.0.0"}

ファイルを保存すると、サーバが自動的に再起動されます。curlコマンドで確認します。

curl http://localhost:8000/about

以下のような結果が表示されます。

{"app_name":"FastAPI Demo","version":"1.0.0"}

/にアクセスするとroot()関数、/aboutにアクセスするとabout()関数がそれぞれ実行されます。このように、デコレータのパスを変えることで、URLごとに異なる処理を割り当てることができます。

5.2 パスパラメータ

パスパラメータとは

パスパラメータは、URLのパスの一部をパラメータとして受け取る仕組みです。基本的な構文は以下のとおりです。

@app.get("/パス/{パラメータ名}")
def 関数名(パラメータ名: 型):
    return データ

パスの中に{パラメータ名}を含めると、その部分がパラメータとして関数の引数に渡されます。

実際に試してみましょう。main.pyに以下のエンドポイントを追加します。

@app.get("/hello/{name}")
def hello(name: str):
    return {"message": f"こんにちは、{name}さん!"}

{name}がパスパラメータです。URLの/hello/の後に指定した値が、関数の引数nameに渡されます。: strの型ヒントにより、FastAPIがパラメータを文字列型として受け取ります。

curl http://localhost:8000/hello/太郎

以下のような結果が表示されます。

{"message":"こんにちは、太郎さん!"}

URLの太郎の部分がパスパラメータとして関数に渡され、f"こんにちは、{name}さん!"によって文字列に組み込まれてレスポンスに反映されています。

パスパラメータの型によるバリデーション

パスパラメータにはint型を指定することもできます。main.pyに以下のエンドポイントを追加します。

@app.get("/items/{item_id}")
def get_item(item_id: int):
    return {"item_id": item_id, "message": f"アイテム{item_id}の情報です"}

item_id: intと型ヒントを指定することで、FastAPIがパスパラメータを自動的に整数型に変換します。

整数を指定してリクエストを送信します。

curl http://localhost:8000/items/3
{"item_id":3,"message":"アイテム3の情報です"}

パスパラメータの3が整数として関数に渡されています。

次に、整数ではない文字列を指定した場合の動作を確認します。

curl http://localhost:8000/items/abc
{"detail":[{"type":"int_parsing","loc":["path","item_id"],"msg":"Input should be a valid integer, unable to parse string as an integer","input":"abc"}]}

item_id: intの型ヒントに基づいて、FastAPIが自動的にバリデーションを行い、整数に変換できない値が渡された場合はエラーレスポンスを返しています。このように、型ヒントを指定するだけでバリデーションが自動化されるのがFastAPIの特徴です。

5.3 クエリパラメータ

クエリパラメータは、URLの?以降にキー=値の形式で指定するパラメータです。基本的な構文は以下のとおりです。

@app.get("/パス")
def 関数名(パラメータ名: 型 = デフォルト値):
    return データ

パスパラメータと異なり、URLのパスには含めず、関数の引数として定義します。デフォルト値を指定するとオプションパラメータになり、省略した場合はデフォルト値が使用されます。

実際に試してみましょう。main.pyに以下のエンドポイントを追加します。

@app.get("/search")
def search(q: str, limit: int = 10):
    return {"query": q, "limit": limit}

qはデフォルト値がないため必須パラメータ、limitはデフォルト値10が設定されているためオプションパラメータです。

両方のパラメータを指定して確認します。

curl "http://localhost:8000/search?q=Python&limit=5"
{"query":"Python","limit":5}

limitを省略した場合はデフォルト値の10が使用されます。

curl "http://localhost:8000/search?q=FastAPI"
{"query":"FastAPI","limit":10}
📝 パスパラメータとクエリパラメータの違い
パスパラメータはURLのパスの一部(/hello/太郎)、クエリパラメータはURLの?以降(/search?q=Python)で値を指定します。一般的に、リソースを特定する場合はパスパラメータ、検索条件やオプションを指定する場合はクエリパラメータが使われます。

5.4 リクエストボディ

POSTPUTメソッドでデータを送信する場合、リクエストのボディにJSONデータを格納します。FastAPIでは、Pydanticモデルを使ってリクエストボディのデータ構造を定義します。

まず、main.pyの先頭のインポート文を以下のように変更します。

from fastapi import FastAPI
from pydantic import BaseModel

from pydantic import BaseModelは、冒頭で紹介したデータバリデーションライブラリPydanticからBaseModelクラスをインポートしています。BaseModelを継承したクラスを定義することで、リクエストボディのデータ構造とバリデーションルールを宣言的に記述できるようになります。

次に、app = FastAPI()の下にPydanticモデルを追加します。

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

BaseModelを継承したクラスを定義し、フィールドに型ヒントを指定します。nameは文字列型、priceは浮動小数点型の必須フィールドです。リクエストボディのJSONデータがこのモデルの構造と一致しない場合、FastAPIが自動的にバリデーションエラーを返します。

エンドポイントを追加します。

@app.post("/items", status_code=201)
def create_item(item: Item):
    return {"message": "アイテムを作成しました", "item": {"name": item.name, "price": item.price}}

関数の引数にPydanticモデルの型ヒント(item: Item)を指定すると、リクエストボディのJSONデータが自動的にモデルに変換され、item.nameitem.priceでアクセスできます。status_code=201は、リソースの作成に成功したことを示すHTTPステータスコード201 Createdをレスポンスに設定します。

curl -X POST http://localhost:8000/items \
  -H "Content-Type: application/json" \
  -d '{"name": "ノート", "price": 250}'
{"message":"アイテムを作成しました","item":{"name":"ノート","price":250.0}}

-X POSTでHTTPメソッドを指定し、-Hでリクエストヘッダ(Content-Type)、-dでリクエストボディ(JSON)を指定しています。

必須フィールドのnameを省略した場合の動作も確認してみましょう。

curl -X POST http://localhost:8000/items \
  -H "Content-Type: application/json" \
  -d '{"price": 250}'

以下のような結果になると思います。

{"detail":[{"type":"missing","loc":["body","name"],"msg":"Field required","input":{"price":250}}]}

Pydanticによるバリデーションが自動的に行われ、nameフィールドが必須であることを示すエラーが返されます。

6. 自動生成ドキュメント(Swagger UI)

FastAPIの大きな特徴の一つとして、APIドキュメントが自動生成されます。サーバが起動している状態で、ブラウザで以下のURLにアクセスしてください。

http://localhost:8000/docs

Swagger UIと呼ばれるインタラクティブなAPIドキュメントが表示されます。このドキュメントでは、定義されているエンドポイントの一覧や、各エンドポイントのリクエスト・レスポンスの仕様を確認できます。さらに、ブラウザ上からAPIのエンドポイントをテスト実行することも可能です。

💡 ポイント
Swagger UIは、APIの仕様を他の開発者に共有する際にも便利です。コードにルーティングや型情報を記述するだけで、ドキュメントが自動的に更新されます。ここまでで追加したエンドポイントもすべてSwagger UIに反映されていますので、確認してみてください。

動作確認が完了したら、ターミナルでCtrl + Cを押してサーバを停止してください。

7. 他のフレームワークとの違い

7.1 フルスタックフレームワークとの違い

DjangoやRuby on Railsなどのフレームワークを学んだことがある方は、FastAPIで覚えることの少なさに驚いたかもしれません。DjangoやRailsはフルスタックフレームワークと呼ばれ、管理画面、テンプレートエンジン、ORM(データベース操作)、認証機能など、Webアプリケーション開発に必要な機能が一通り含まれています。

一方、FastAPIは軽量なフレームワークであり、APIのルーティングとリクエスト/レスポンス処理に特化しています。必要な機能は外部ライブラリを組み合わせて実現するスタイルです。機能が少ないぶんシンプルで学習コストが低く、REST APIやマイクロサービスの開発に適しています。

項目 FastAPI Django / Rails
分類 軽量フレームワーク フルスタックフレームワーク
管理画面 なし あり(Django Adminなど)
テンプレートエンジン なし あり(Django Template、ERBなど)
ORM なし(別途選択) あり(Django ORM、ActiveRecordなど)
学習コスト 低い 高い
主な用途 REST API、マイクロサービス Webアプリケーション全般

7.2 データベース操作について

DjangoにはDjango ORM、Ruby on RailsにはActiveRecordというORM(Object-Relational Mapping)が標準で組み込まれています。ORMとは、データベースのテーブルをクラスとして扱い、SQLを直接書かずにデータベースを操作できる仕組みです。

FastAPIにはORMが含まれていないため、データベース操作のライブラリを自分で選んで組み合わせます。代表的な選択肢は以下のとおりです。

ライブラリ 特徴
SQLAlchemy Pythonで最も広く使われているORM
SQLModel FastAPIの作者が開発したライブラリ。SQLAlchemyとPydanticを統合している
mysql-connector-python ORMを使わず、SQLを直接記述して操作する

次の講座SQLModel入門では、FastAPIの作者が開発したSQLModelというORMライブラリを学びます。SQLModelはSQLAlchemyとPydanticを統合しており、この講座で学んだPydanticモデルの知識をそのままデータベース操作に活かすことができます。

7.3 Pythonの他のWebフレームワーク

Python用のWebフレームワークはFastAPI以外にも存在します。代表的なものを紹介します。

フレームワーク 特徴
Django フルスタックフレームワーク。管理画面やORMが組み込まれており、大規模なWebアプリケーション開発に適している
Flask FastAPIと同じ軽量フレームワーク。シンプルで自由度が高く、長年にわたり広く使われている
FastAPI 軽量フレームワーク。型ヒントによる自動バリデーションとSwagger UIの自動生成が特徴で、REST APIの開発に適している

FlaskとFastAPIはどちらも軽量フレームワークですが、FastAPIは型ヒントを活用した自動バリデーションやドキュメント生成など、より現代的な機能を備えています。

8. まとめ

このハンズオンでは、FastAPIの基本的な使い方を体験しました。

  • FastAPIは、Pythonで高性能なAPIを構築するためのWebフレームワークである
  • uvicorn main:app --reloadでサーバを起動し、--reloadオプションで開発中のコード変更を自動で反映できる
  • デコレータ@app.getなど)でHTTPメソッドとパスを定義し、ルーティングを行う
  • 関数が辞書型を返すと、自動的にJSON形式に変換されてレスポンスとして返される
  • パスパラメータ/hello/{name})でURLの一部をパラメータとして受け取れる
  • クエリパラメータ/search?q=Python)でURLの?以降にパラメータを指定できる
  • Pydanticモデルでリクエストボディのバリデーションを自動化できる
  • status_code=201でレスポンスのステータスコードを指定できる
  • Swagger UI/docs)でAPIドキュメントが自動生成され、ブラウザ上からテスト実行もできる