吃透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={...}参数
相关推荐
爱音乐的marlon9 小时前
FastAPI 学习笔记03|core 核心层:config 是总控制台,database 是整个工程的地基
笔记·学习·fastapi
花酒锄作田12 小时前
Repository 模式在 FastAPI 中的应用
python·fastapi
喜欢的名字被抢了20 小时前
FastAPI 接口安全与工程化 JWT、测试和配置管理
安全·fastapi
Maiko Star2 天前
从零落地「AI掘金头条」新闻模块:FastAPI + SQLAlchemy 异步实战
python·fastapi
喜欢的名字被抢了2 天前
FastAPI 接入异步 PostgreSQL 完成任务 CRUD 与数据库迁移
数据库·postgresql·fastapi
Esaka_Forever2 天前
uvicorn main.py 命令说明
fastapi
巴啦啦小魔仙变身3 天前
FastAPI 01 Create Demo
python·fastapi
李昊哲小课4 天前
fastapi sse websocket 奶茶店实时订单看板
人工智能·python·websocket·网络协议·fastapi·sse
李昊哲小课5 天前
fastapi sse websocket 智能家居实时控制台
python·websocket·智能家居·fastapi·sse
赵广陆5 天前
SQLAlchemy ORM 超全教程
python·fastapi