吃透FastAPI的响应类型

  1. 最傻瓜的方式:直接返回字典(默认JSON响应)

这是你最先接触的用法。FastAPI会自动把字典、列表等转成JSON,并设置响应头Content-Type: application/json。

复制代码
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    # 直接返回一个字典
    return {"message": "Hello World"}

访问机会得到:

复制代码
{"message": "Hello World"}
  1. 用response_model规定输出的数据形状

response_model就像一个质检员,它会:

把你函数返回的数据转换成指定的Pydantic模型结构

过滤掉不想让客户端看到的字段(比如密码)

自动生成API文档

复制代码
from pydantic import BaseModel

class UserIn(BaseModel):      # 用于输入(注册)
    username: str
    password: str

class UserOut(BaseModel):     # 用于输出(返回给客户端)
    username: str

@app.post("/user", response_model=UserOut)
def create_user(user: UserIn):
    # 虽然返回的是包含password的user,但response_model会把它过滤掉
    return user

客户端调用后只会收到 {"username": "xxx"},password字段被自动去除。

怎么用:

把Pydantic模型写在装饰器的response_model参数里

还可以用response_model_include/response_model_exclude进一步控制显示/隐藏字段

如果不需要过滤,可以不写response_model,但写上可以提高文档质量和安全性

  1. 直接返回各种"封装好的响应盒子"(Response对象)

当你想控制更多细节(比如状态码、响应头、Cookie,或者返回非JSON内容)时,就要直接返回一个Response对象或其子类。这些类都在fastapi.responses里。

📦 JSONResponse ------ 手工打造JSON响应

如果你需要在返回JSON的同时设置自定义头或状态码,就可以用这个。

复制代码
from fastapi.responses import JSONResponse

@app.get("/custom-json")
def custom_json():
    content = {"msg": "手工打造"}
    return JSONResponse(
        content=content,
        status_code=201,               # 自定义状态码
        headers={"X-Custom": "foo"}    # 自定义响应头
    )

📄 HTMLResponse ------ 返回网页

复制代码
from fastapi.responses import HTMLResponse

@app.get("/page", response_class=HTMLResponse)
def get_page():
    html = "<h1>你好</h1><p>这是HTML页面</p>"
    return html

你也可以不用response_class参数,直接返回HTMLResponse实例:

复制代码
return HTMLResponse(content="<h1>...</h1>", status_code=200)

✍️ PlainTextResponse ------ 纯文本

复制代码
from fastapi.responses import PlainTextResponse

@app.get("/text", response_class=PlainTextResponse)
def get_text():
    return "这是一段纯文本,不是HTML也不是JSON"

🔄 RedirectResponse ------ 重定向

复制代码
from fastapi.responses import RedirectResponse

@app.get("/old")
def old_page():
    return RedirectResponse("/new-page")

访问 /old 时,浏览器会自动跳转到/new-page。

📁 FileResponse ------ 文件下载

复制代码
from fastapi.responses import FileResponse

@app.get("/download")
def download():
    file_path = "example.png"
    return FileResponse(
        path=file_path,
        filename="download-name.png",   # 让浏览器看到的名字
        media_type="image/png"          # 可选,自动识别
    )

🌊 StreamingResponse ------ 流式响应(大数据、实时输出)

适合返回很大的数据流(如AI生成内容、视频流、SSE)。

复制代码
from fastapi.responses import StreamingResponse

def data_generator():
    for i in range(10):
        yield f"第{i}条数据\n"

@app.get("/stream")
def stream():
    return StreamingResponse(data_generator(), media_type="text/plain")
  1. 在装饰器里设置response_class ------ 改变默认响应格式

如果你希望一个路由返回某些内容时,自动被包裹成指定的响应类(而不用在函数内手动创建响应对象),就用response_class参数。

最常见的例子:返回字符串时,默认是JSON字符串(带引号),但我们想返回HTML/纯文本。

复制代码
@app.get("/auto-html", response_class=HTMLResponse)
def auto_html():
    # 直接返回字符串,FastAPI会用HTMLResponse包装
    return "<h1>我是自动生成的HTML</h1>"

如果不写response_class=HTMLResponse,你会看到带引号的字符串 "<h1>...</h1>",而不是被浏览器渲染的HTML。

总结:response_class相当于告诉FastAPI:"这个路由内部返回的任何数据,都用这种盒子发出去"。

  1. 文档中声明额外响应(不同状态码的模型)

当你希望OpenAPI文档里展示某个接口在错误状态码(如404)时返回的数据结构,可以使用responses参数。

复制代码
from pydantic import BaseModel

class Message(BaseModel):
    message: str

@app.get(
    "/items/{item_id}",
    response_model=dict,
    responses={
        404: {"model": Message, "description": "物品未找到"},
        200: {"description": "成功返回物品数据"}
    }
)
async def read_item(item_id: str):
    if item_id != "123":
        return JSONResponse(status_code=404, content={"message": "找不到物品"})
    return {"item_id": item_id, "value": "重要资料"}

这样Swagger文档里就会清楚说明404会返回{"message": "..."}。

  1. 更高级的响应类(性能优化)

如果对JSON序列化性能有要求,可以安装orjson,然后使用ORJSONResponse替代默认的JSONResponse。

复制代码
from fastapi.responses import ORJSONResponse

app = FastAPI(default_response_class=ORJSONResponse)  # 全局使用

@app.get("/fast-json")
def fast_json():
    return {"data": [1,2,3]}

总结:什么时候用什么?

复制代码
你想要的响应                                    用什么
返回JSON字典/列表,接受默认状态码200              直接return dict
返回JSON但想把密码等字段藏起来                    加response_model=OutputModel
返回JSON需要自定义状态码/头部                     return JSONResponse(...)
返回HTML、纯文本、重定向、文件、流                使用对应的HTMLResponse等
整个路由都要返回HTML(简化代码)                  装饰器里写response_class=HTMLResponse
需要在文档里标明404等错误格式                     使用responses={...}参数
相关推荐
尘埃落定wf6 小时前
用 FastAPI 将 LangChain Agent 封装成对外接口
langchain·fastapi
曲幽2 天前
FastAPI + SQLAlchemy 2.0 通用CRUD操作手册 —— 从同步到异步,一次讲透
python·fastapi·web·async·sqlalchemy·session·crud·sync·with
wytraining2 天前
快速入门 FastAPI 项目
jvm·oracle·fastapi
码界筑梦坊2 天前
94-基于Python的商品物流数据可视化分析系统
开发语言·python·mysql·信息可视化·数据分析·毕业设计·fastapi
zhz52142 天前
一个简单、轻量级且安全的离线GIS 系统架构设计
安全·系统架构·vue·gis·fastapi
L-影3 天前
FastAPI全解析(下):除了快,它还能干多少脏活累活?
python·fastapi
码界筑梦坊3 天前
302-基于Python的安卓应用市场数据可视化分析推荐系统
开发语言·python·信息可视化·毕业设计·fastapi
Ares-Wang3 天前
flask、flask-restful、fastAPI
flask·restful·fastapi
fTiN CAPA3 天前
开源模型应用落地-FastAPI-助力模型交互-进阶篇-中间件(四)
开源·交互·fastapi