附加状态码¶
默认情况下,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)
🤓 Other versions and variants
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
Prefer to use the Annotated version if possible.
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
Prefer to use the Annotated version if possible.
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 提供与 starlette.responses 相同的 fastapi.responses,只是为了方便开发者。但大部分可用的响应直接来自 Starlette。status 也是如此。
OpenAPI 和 API 文档¶
如果你直接返回附加状态码和响应,它们不会被包含在 OpenAPI 模式(API 文档)中,因为 FastAPI 无法事先知道你将返回什么。
但你可以在代码中使用以下方式记录:附加响应。