追加のステータスコード¶
デフォルトでは、FastAPIはJSONResponseを使用してレスポンスを返し、パス操作から返されるコンテンツをそのJSONResponse内に配置します。
デフォルトのステータスコード、またはパス操作で設定したステータスコードを使用します。
追加のステータスコード¶
メインのステータスコードとは別に、追加のステータスコードを返したい場合は、JSONResponseのようなResponseを直接返し、追加のステータスコードを直接設定することで実現できます。
例えば、アイテムを更新するパス操作があり、成功した場合はHTTPステータスコード200 "OK"を返すとします。
しかし、新しいアイテムも受け入れたいとします。そして、アイテムが以前に存在しなかった場合は、それらを作成し、HTTPステータスコード201 "Created"を返します。
これを実現するには、JSONResponseをインポートし、コンテンツを直接そこに返し、必要なstatus_codeを設定します。
from typing import Annotated
from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse
app = FastAPI()
items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
@app.put("/items/{item_id}")
async def upsert_item(
item_id: str,
name: Annotated[str | None, Body()] = None,
size: Annotated[int | None, Body()] = None,
):
if item_id in items:
item = items[item_id]
item["name"] = name
item["size"] = size
return item
else:
item = {"name": name, "size": size}
items[item_id] = item
return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
🤓 その他のバージョンとバリアント
from typing import Annotated, Union
from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse
app = FastAPI()
items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
@app.put("/items/{item_id}")
async def upsert_item(
item_id: str,
name: Annotated[Union[str, None], Body()] = None,
size: Annotated[Union[int, None], Body()] = None,
):
if item_id in items:
item = items[item_id]
item["name"] = name
item["size"] = size
return item
else:
item = {"name": name, "size": size}
items[item_id] = item
return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
from typing import Union
from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse
from typing_extensions import Annotated
app = FastAPI()
items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
@app.put("/items/{item_id}")
async def upsert_item(
item_id: str,
name: Annotated[Union[str, None], Body()] = None,
size: Annotated[Union[int, None], Body()] = None,
):
if item_id in items:
item = items[item_id]
item["name"] = name
item["size"] = size
return item
else:
item = {"name": name, "size": size}
items[item_id] = item
return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
ヒント
可能であれば`Annotated`バージョンを使用することをお勧めします。
from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse
app = FastAPI()
items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
@app.put("/items/{item_id}")
async def upsert_item(
item_id: str,
name: str | None = Body(default=None),
size: int | None = Body(default=None),
):
if item_id in items:
item = items[item_id]
item["name"] = name
item["size"] = size
return item
else:
item = {"name": name, "size": size}
items[item_id] = item
return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
ヒント
可能であれば`Annotated`バージョンを使用することをお勧めします。
from typing import Union
from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse
app = FastAPI()
items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
@app.put("/items/{item_id}")
async def upsert_item(
item_id: str,
name: Union[str, None] = Body(default=None),
size: Union[int, None] = Body(default=None),
):
if item_id in items:
item = items[item_id]
item["name"] = name
item["size"] = size
return item
else:
item = {"name": name, "size": size}
items[item_id] = item
return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
Warning
上記の例のように、Responseを直接返すと、それは直接返されます。
モデルなどでシリアライズされることはありません。
必要なデータが含まれており、値が有効なJSONであることを確認してください(JSONResponseを使用している場合)。
技術的な詳細
from starlette.responses import JSONResponseを使用することもできます。
FastAPIは、開発者にとっての利便性として、starlette.responsesと全く同じものをfastapi.responsesとして提供しています。しかし、利用可能なレスポンスのほとんどはStarletteから直接来ています。statusも同様です。
OpenAPIとAPIドキュメント¶
追加のステータスコードとレスポンスを直接返した場合、それらはOpenAPIスキーマ(APIドキュメント)には含まれません。なぜなら、FastAPIは、あなたが何を返すかを事前に知る方法がないからです。
しかし、追加のレスポンスを使用して、コード内でそれを文書化することができます。