コンテンツにスキップ

追加のステータスコード

デフォルトでは、**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ドキュメント

追加のステータスコードとレスポンスを直接返すと、FastAPI は事前に何を返すかを知る方法がないため、OpenAPI スキーマ(API ドキュメント)には含まれません。

ただし、追加のレスポンスを使用して、コードにドキュメント化できます。