はじめに
こんにちは、いのせです。
今回は、研修チーム開発で用いたFastAPIをハンズオン形式で学べるように初学者向けに書いてみました。
FastAPIは、Pythonで簡単にWeb APIを作ることができるフレームワークです。
このハンズオンでは、基本的なところから、ステップバイステップで学んでいきます。
FastAPIとは
FastAPIは、Pythonで高速かつ簡単にWeb APIを構築するためのモダンなフレームワークです。非同期処理をサポートし、StarletteとPydanticを基盤にしているため、高パフォーマンスで型安全なAPI開発が可能です。自動生成されるOpenAPIドキュメント(Swagger UI)により、APIのテストやドキュメント化が容易です。主に、効率的でスケーラブルなWebアプリケーションやマイクロサービスの構築に使用されます。
今回作るもの
シンプルな本の管理APIを作ります。
本を追加したり、一覧を見たり、削除したりできるAPIです。
事前準備
必要なもの
- Python 3.7以上
- テキストエディタ(メモ帳でもOK、VS Codeがおすすめ)
インストール
# ターミナル(コマンドプロンプト)で実行
pip install fastapi uvicorn
Step 1: 一番シンプルなAPI - Hello World
ファイルを作成
main.py
というファイルを作って、以下を書いてください:
from fastapi import FastAPI
# FastAPIアプリを作成
app = FastAPI()
@app.get("/")
def hello():
return {"message": "Hello World!"}
🔍 FastAPI特有の機能解説
FastAPI()
とは?
app = FastAPI()
- これがFastAPIアプリケーションの「土台」を作る命令です
-
app
という名前で、APIの機能をまとめる箱を作ったと思ってください
@app.get("/")
とは?
@app.get("/")
def hello():
return {"message": "Hello World!"}
-
@app.get
は「GETリクエストを受け取る」という意味のデコレータです -
"/"
は URL のパス(アドレス)です - つまり「トップページ(/)にGETリクエストが来たら、hello関数を実行して」という意味
戻り値について
return {"message": "Hello World!"}
- FastAPIでは、辞書(dict)を返すと自動的にJSON形式に変換されます
- つまり
{"message": "Hello World!"}
が JSON として返されます
実行してみよう
uvicorn main:app --reload
ブラウザで http://127.0.0.1:8000
にアクセスしてみてください。
Step 2: データを扱う - Pydanticモデル
本のデータ構造を定義
main.py
を以下のように書き換えてください:
from fastapi import FastAPI
from pydantic import BaseModel
# FastAPIアプリを作成
app = FastAPI()
# 本のデータ構造を定義
class Book(BaseModel):
title: str # タイトル(文字列)
author: str # 著者(文字列)
pages: int # ページ数(整数)
published: bool # 出版済みかどうか(True/False)
@app.get("/")
def hello():
return {"message": "本の管理APIです"}
🔍 Pydantic特有の機能解説
BaseModel
とは?
from pydantic import BaseModel
class Book(BaseModel):
title: str
author: str
pages: int
published: bool
-
BaseModel
は、データの「型」を定義するためのクラスです -
title: str
は「titleは文字列(string)型」という意味 -
pages: int
は「pagesは整数(integer)型」という意味 -
published: bool
は「publishedは真偽値(boolean)型」という意味
なぜこれが重要?
- 自動バリデーション: 間違った型のデータが来ると、自動的にエラーになります
- 自動文書化: API文書に、どんなデータが必要かが自動で表示されます
- エディタサポート: VS Codeなどで、入力補完が効きます
Step 3: データを保存する場所を作る
メモリ上にデータを保存
main.py
に以下を追加:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Book(BaseModel):
title: str
author: str
pages: int
published: bool
# 本のデータを保存するリスト(本来はデータベースを使います)
books = []
@app.get("/")
def hello():
return {"message": "本の管理APIです"}
# 本の一覧を取得
@app.get("/books")
def get_books():
return books
🔍 リストとエンドポイントの解説
グローバル変数 books
books = []
- 本のデータを保存するための空のリストです
- 本来はデータベースを使いますが、今回は学習のためリストを使います
- プログラムを再起動すると、データは消えてしまいます
新しいエンドポイント
@app.get("/books")
def get_books():
return books
-
/books
というURLで本の一覧を取得できます - 最初は空のリスト
[]
が返されます
実行して確認
http://127.0.0.1:8000/books
にアクセスしてみてください。空のリスト []
が表示されるはずです。
Step 4: 本を追加する機能
POSTエンドポイントを追加
main.py
に以下を追加:
@app.post("/books")
def add_book(book: Book):
books.append(book)
return {"message": "本を追加しました", "book": book}
🔍 POSTエンドポイントの解説
@app.post
とは?
@app.post("/books")
def add_book(book: Book):
-
@app.post
は「POSTリクエストを受け取る」という意味 - GETは「データを取得」、POSTは「データを送信・作成」に使います
引数 book: Book
とは?
def add_book(book: Book):
-
book
という名前の引数を受け取ります -
Book
型なので、Bookクラスの形式でデータが送られてきます - FastAPIが自動的にJSONをBookオブジェクトに変換してくれます
リストへの追加
books.append(book)
- 受け取った本のデータを、
books
リストに追加します
テストしてみよう
-
http://127.0.0.1:8000/docs
にアクセス -
POST /books
をクリック -
「Try it out」をクリック
-
以下のような JSON を入力:
{ "title": "Python入門", "author": "田中太郎", "pages": 300, "published": true }
-
「Execute」をクリック
そして http://127.0.0.1:8000/books
で本が追加されているか確認してみてください!
Step 5: 特定の本を取得する
パスパラメータを使う
main.py
に以下を追加:
@app.get("/books/{book_id}")
def get_book(book_id: int):
if book_id < len(books):
return books[book_id]
return {"error": "本が見つかりません"}
🔍 パスパラメータの解説
{book_id}
とは?
@app.get("/books/{book_id}")
def get_book(book_id: int):
- URLの一部を変数として受け取ることができます
- 例:
/books/0
ならbook_id
は 0 - 例:
/books/1
ならbook_id
は 1 -
book_id: int
と書くことで、整数のみ受け付けるようになります
リストのインデックス
if book_id < len(books):
return books[book_id]
-
len(books)
はリストの長さ(要素数) -
books[0]
は最初の本、books[1]
は2番目の本 - 存在しないインデックスの場合は、エラーメッセージを返します
テストしてみよう
- 先ほど本を1冊追加していれば、
http://127.0.0.1:8000/books/0
にアクセス - その本の情報が表示されるはず
-
http://127.0.0.1:8000/books/999
にアクセスして、エラーメッセージも確認
Step 6: 本を削除する機能
DELETEエンドポイントを追加
main.py
に以下を追加:
@app.delete("/books/{book_id}")
def delete_book(book_id: int):
if book_id < len(books):
deleted_book = books.pop(book_id)
return {"message": "本を削除しました", "deleted_book": deleted_book}
return {"error": "本が見つかりません"}
🔍 DELETEエンドポイントの解説
@app.delete
とは?
@app.delete("/books/{book_id}")
- DELETEは「データを削除」する時に使うHTTPメソッドです
- GET(取得)、POST(作成)、DELETE(削除)が基本的な操作です
pop()
メソッド
deleted_book = books.pop(book_id)
-
pop(book_id)
は、指定したインデックスの要素を削除して、その要素を返すメソッドです - 削除された本の情報も返すので、ユーザーに「何を削除したか」を教えることができます
Step 7: エラーハンドリングを改善
HTTPExceptionを使う
main.py
の先頭に追加:
from fastapi import FastAPI, HTTPException
そして、エラー処理を以下のように変更:
@app.get("/books/{book_id}")
def get_book(book_id: int):
if book_id < 0 or book_id >= len(books):
raise HTTPException(status_code=404, detail="本が見つかりません")
return books[book_id]
@app.delete("/books/{book_id}")
def delete_book(book_id: int):
if book_id < 0 or book_id >= len(books):
raise HTTPException(status_code=404, detail="本が見つかりません")
deleted_book = books.pop(book_id)
return {"message": "本を削除しました", "deleted_book": deleted_book}
🔍 HTTPExceptionの解説
HTTPException
とは?
from fastapi import FastAPI, HTTPException
raise HTTPException(status_code=404, detail="本が見つかりません")
- 適切なHTTPステータスコードでエラーを返すためのクラスです
-
status_code=404
は「Not Found(見つからない)」という意味 -
detail
はエラーの詳細メッセージです
なぜ raise
を使う?
-
return
でエラーを返すと、ステータスコードは200(成功)になってしまいます -
raise HTTPException
を使うと、適切なエラーステータスコードが返されます - APIを使う側(フロントエンドなど)が、成功かエラーかを正しく判断できます
Step 8: 完成したコード全体
最終的な main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
# FastAPIアプリを作成
app = FastAPI(title="本の管理API", description="初心者向けの本管理システム")
# 本のデータ構造を定義
class Book(BaseModel):
title: str # タイトル
author: str # 著者
pages: int # ページ数
published: bool # 出版済みかどうか
# 本のデータを保存するリスト
books = []
@app.get("/")
def hello():
"""APIの基本情報"""
return {
"message": "本の管理APIです",
"endpoints": {
"本の一覧": "GET /books",
"本の追加": "POST /books",
"特定の本": "GET /books/{id}",
"本の削除": "DELETE /books/{id}"
}
}
@app.get("/books")
def get_books():
"""すべての本を取得"""
return {"books": books, "count": len(books)}
@app.post("/books")
def add_book(book: Book):
"""新しい本を追加"""
books.append(book)
return {
"message": "本を追加しました",
"book": book,
"total_books": len(books)
}
@app.get("/books/{book_id}")
def get_book(book_id: int):
"""特定の本を取得"""
if book_id < 0 or book_id >= len(books):
raise HTTPException(status_code=404, detail="本が見つかりません")
return books[book_id]
@app.delete("/books/{book_id}")
def delete_book(book_id: int):
"""本を削除"""
if book_id < 0 or book_id >= len(books):
raise HTTPException(status_code=404, detail="本が見つかりません")
deleted_book = books.pop(book_id)
return {
"message": "本を削除しました",
"deleted_book": deleted_book,
"remaining_books": len(books)
}
実行方法
uvicorn main:app --reload
使い方
-
API文書を見る:
http://127.0.0.1:8000/docs
-
基本情報:
http://127.0.0.1:8000/
-
本の一覧:
http://127.0.0.1:8000/books
最後に
今回はFastAPI初学者でもわかるようにハンズオン形式で本の管理APIの開発を行いました。
これよりももっと発展させていきたい場合は、公式ドキュメントなどを読んで開発をしてみてください!
チュートリアルもおすすめです。