直接返回响应¶
当你创建一个 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 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,同时仍然可以进行自动数据转换、生成文档等。