直接返回响应¶
当你创建一个 FastAPI 的路径操作时,通常可以从它返回任何数据:dict、list、Pydantic 模型、数据库模型等。
默认情况下,FastAPI 会使用 JSON 兼容编码器 中解释的 jsonable_encoder 自动将该返回值转换为 JSON。
然后,在幕后,它会将该 JSON 兼容数据(例如 dict)放入一个 JSONResponse 中,然后发送给客户端。
但是你可以直接从你的路径操作中返回一个 JSONResponse。
例如,这可能有助于返回自定义的头部信息或 Cookie。
返回一个 Response¶
实际上,你可以返回任何 Response 或它的任何子类。
提示
JSONResponse 本身就是 Response 的一个子类。
当你返回一个 Response 时,FastAPI 会直接传递它。
它不会对 Pydantic 模型进行任何数据转换,也不会将内容转换为任何类型等。
这为你提供了极大的灵活性。你可以返回任何数据类型,覆盖任何数据声明或验证等。
在 Response 中使用 jsonable_encoder¶
因为 FastAPI 不会对你返回的 Response 进行任何更改,所以你必须确保它的内容已经准备好。
例如,在将 Pydantic 模型放入 JSONResponse 之前,你必须先将其转换为 dict,并将所有数据类型(如 datetime、UUID 等)转换为 JSON 兼容类型。
对于这些情况,你可以使用 jsonable_encoder 在将数据传递给响应之前进行转换。
from datetime import datetime
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from pydantic import BaseModel
class Item(BaseModel):
title: str
timestamp: datetime
description: str | None = None
app = FastAPI()
@app.put("/items/{id}")
def update_item(id: str, item: Item):
json_compatible_item_data = jsonable_encoder(item)
return JSONResponse(content=json_compatible_item_data)
🤓 其他版本和变体
from datetime import datetime
from typing import Union
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from pydantic import BaseModel
class Item(BaseModel):
title: str
timestamp: datetime
description: Union[str, None] = None
app = FastAPI()
@app.put("/items/{id}")
def update_item(id: str, item: Item):
json_compatible_item_data = jsonable_encoder(item)
return JSONResponse(content=json_compatible_item_data)
技术细节
你也可以使用 from starlette.responses import JSONResponse。
FastAPI 提供与 fastapi.responses 相同的 starlette.responses 只是为了方便开发者。但大多数可用的响应直接来自 Starlette。
返回自定义 Response¶
上面的示例显示了所有你需要的部分,但它还不是很有用,因为你可以直接返回 item,而 FastAPI 会为你将其放入 JSONResponse 中,并将其转换为 dict 等。所有这些都是默认操作。
现在,让我们看看你如何使用它来返回一个自定义响应。
假设你想返回一个 XML 响应。
你可以将 XML 内容放入一个字符串中,然后将其放入一个 Response 并返回。
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/legacy/")
def get_legacy_data():
data = """<?xml version="1.0"?>
<shampoo>
<Header>
Apply shampoo here.
</Header>
<Body>
You'll have to use soap here.
</Body>
</shampoo>
"""
return Response(content=data, media_type="application/xml")
注意事项¶
当你直接返回 Response 时,其数据不会自动进行验证、转换(序列化)或记录。
但是,你仍然可以按照 OpenAPI 中的附加响应 中的描述进行记录。
在后面的部分中,你可以看到如何在拥有自动数据转换、记录等功能的同时,使用/声明这些自定义 Response。