コンテンツへスキップ

追加のステータスコード

デフォルトでは、FastAPIJSONResponseを使用して応答を返し、パス操作から返されるコンテンツをその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は何を返すか事前に知る方法がないからです。

しかし、追加の応答を使用して、コードでそれをドキュメント化できます。