はじめに
Fast APIの公式チュートリアルをやってみた
やった範囲
チュートリアルユーザーガイド ~ クエリパラメーターと文字列の検証まで
ここまででFast APIの特徴やGET POST path paramerter query paramerterなど基本的なことを学べます
チュートリアルはこの先も続くのですが、概要を把握するだけならここまででも把握できます。 FastAPIの楽しさや便利さを味わえます
チュートリアルをまとめてみる
基本
# base
from fastapi import FastAPI # Starletteを継承している
app = FastAPI() # instance
@app.get("/") # path operation(HTTP method) decorate
async def root(): # path operation function
return {"message": "Hello World"} # jsonに変換
path parameter
# path parameter
@app.get("/items/{id}")
async def read_item(id: int): # 型を指定する
return {"item_id": item_id}
# 型をintにした時 idはint型にサニタライズされる
# 型をintにしていない時 デフォルトの文字列で受け取る
# Enum
# 型と固定値(選択肢)を定義
from enum import Enum
class ModelName(str, Enum):
tee = "tee"
baru = "baru"
@app.get("/models/{name}"):
async def greet(name: ModelName)
if name is ModelName.tee:
return { "message": "おはようtee" }
return { "message": "こんにちはbaru" }
# file pathなど PATH(/)を含むpath parameterを受け取る
@app.get("/files/{file_path:path}"): # :path
async def read_file(file_path: str): # str
return {"file_path": file_path}
# PATHの最初に/を含ませたい場合 URLは/を重ねる (//)
query parameter
query parameterはデフォルト値やオプショナルも受け取れる
query paramerterを配列で受け取る場合はQueryを使用する必要がある
# query parameter
# path parameterで定義されていなければ自動でqueryと解釈
# query parameterはOptionalにしたり、default値を持てる
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
# デフォルト値あり
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
return fake_items_db[skip : skip + limit]
# オプショナル
from typing import Union
# デフォルト値を Noneにすればオプションになる
# FastAPIでUnionは使用していない。 エディターのサポートで有効
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None):
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
# bool型もsanitization(変換)する
@app.get("/bool")
async def check_bool(q: bool = False):
if q:
return {"message": "true"}
return {"message": "false"}
# query paramsのvalidation
from fastapi import FastAPI, Query
from typing import Union
# オプション && 存在する時は5文字以下
# 必須 && validationをする場合 第1引数に...を指定する
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=5)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
# query pramerterを配列で受けとる
# queryを使わずにList[]を使うとrequest bodyとして解釈される
@app.get("/items/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
query_items = {"q": q}
return query_items
https://fastapi.tiangolo.com/ja/tutorial/query-params-str-validations/
POST
from fastapi import FastAPI
from typing import Union
from pydantic import BaseModel
# Pydanticを使用して、受け取るrequest bodyを定義する
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
# この時点のitem typeはclass instance
# 処理する場合dict()で辞書に変換してから処理する
return items
# pathから受け取るのか、bodyから受け取るのかは自動で判断する
@app.put("/items/{item_id}")
async def create_item(item_id: int, item: Item):
return {"item_id": item_id, **item.dict()}
説明を省いて載っける
超基礎的な部分のみを綺麗に抽出
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
# path paramerter
@app.get("/path/{id}")
async def path(id: int):
return {"id": id}
# query paramerter
@app.get("/query")
async def query(q: Union[str, None] = None):
if q:
return {"query": q}
return {"message": "queryは渡されませんでした"}
# request body
class User(BaseModel):
name: st
age: int
email: str
password: str
@app.post("/signup")
async def create_user(user: User):
return user
Fast APIの何が良いのか
Fast APIは巨人の方に乗っています。
Paydanticによる恩恵は素晴らしいです
Paydanticはvalidation機能を提供しますが、同時にsanitizeもします
# 型なし
@app.get("/path/{id}")
async def path(id):
return {"id": id} # url paramerterから取得した値はstringになる
# 型あり
@app.get("/path/{id}")
async def path(id: int):
return {"id": id} # int型
通常はintに変換する作業を自前で書かないといけなのですが、pydanticの力でsanitize(変換)してくれています
もちろん変換できない値を入れた場合適切なエラーを表示します
pathなのかrequestなのかqueryなのかを自動で判断する
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def create_item(item_id: int, item: Item, q: Union[str, None] = None):
if q:
return {"item_id": item_id, **item.dict(), "query": q}
return {"item_id": item_id, **item.dict()}
expressと比較してみる
// どこから取るのかハンドリングする必要がある
app.get("/:path", async (req, res) => {
const { path } = req.params; // path params
const { query } = req.query; // query params
const user = req.body; // request body
const obj = {
...user,
path,
query,
};
res.json(obj);
});
自動ドキュメント生成
/docsや/redocにアクセスすると、作成したAPIに紐づいたドキュメントを見ることができます。
Postmanを使わずにAPIの検証を行うことができる + ドキュメントを自前で用意する必要がない
APIを作る専用のフレームワークであることもメリットだと感じました。
終わりに
UdemyをFastAPIを学習する前に公式ドキュメントで触ってみました。
公式ドキュメントにはFastAPIの仕組みや、ここに載せていない細かい情報まで大変参考になりました。
FastAPIはシンプルなので結構好きです
2018年からのスタートなので、まだまだ伸びていくと思います。
公式ドキュメントは一部日本語化もされていて非常に読みやすいのでぜひ読んでみてください
下記にDockerの環境構築方法も載せています!! よかったら使ってください