Skip to content

附加状态码

默认情况下,FastAPI 会使用 JSONResponse 返回响应,将你在 路径操作 中返回的内容放入该 JSONResponse 中。

它会使用默认的状态码或你在 路径操作 中设置的状态码。

附加状态码

如果你想返回除主要状态码之外的其他状态码,你可以通过直接返回一个 Response,比如 JSONResponse,并直接设置附加的状态码来实现。

例如,假设你有一个 路径操作,允许更新项目,并在成功时返回 HTTP 状态码 200 "OK"。

但你还需要接受新项目。当项目之前不存在时,它会创建它们,并返回 HTTP 状态码 201 "Created"。

要实现这一点,请导入 JSONResponse,并直接在其中返回你的内容,设置你想要的状态码:

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)

Tip

如果可能,建议使用 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)

Tip

如果可能,建议使用 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 提供了与 fastapi.responses 相同的 starlette.responses,只是为了方便你,开发者。但大多数可用的响应直接来自 Starlette。与 status 相同。

OpenAPI 和 API 文档

如果你直接返回附加的状态码和响应,它们不会包含在 OpenAPI 模式(API 文档)中,因为 FastAPI 无法提前知道你要返回什么。

但你可以在代码中使用以下方式进行文档化:附加响应