跳到内容

附加状态码

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

它将使用默认状态码,或您在路径操作中设置的状态码。

附加状态码

如果您想除了主状态码之外还返回附加状态码,您可以通过直接返回一个 Response(例如 JSONResponse),并直接设置附加状态码来实现。

例如,假设您想要一个允许更新项目的路径操作,并在成功时返回 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 提供了与 fastapi.responses 相同的 starlette.responses,仅仅是为了方便您这位开发者。但大多数可用的响应都直接来自 Starlette。status 也是如此。

OpenAPI 和 API 文档

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

但您可以在代码中进行文档说明,使用:附加响应