追加のステータスコード¶
デフォルトでは、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)
警告
上記の例のように、Response
を直接返すと、それは直接返されます。
モデルなどでシリアライズされることはありません。
必要なデータが含まれており、値が有効なJSON(JSONResponse
を使用している場合)であることを確認してください。
技術的な詳細
また、from starlette.responses import JSONResponse
を使用することもできます。
FastAPIは、開発者にとっての利便性として、starlette.responses
と同じものをfastapi.responses
として提供しています。しかし、利用可能なほとんどの応答はStarletteから直接来ています。status
も同様です。
OpenAPIとAPIドキュメント¶
追加のステータスコードと応答を直接返した場合、それらはOpenAPIスキーマ(APIドキュメント)には含まれません。なぜなら、FastAPIは何を返すか事前に知る方法がないからです。
しかし、追加の応答を使用して、コードでそれをドキュメント化できます。