吃透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={...}参数
相关推荐
曲幽2 小时前
FastAPI 身份验证总踩坑?这份 FastAPI Users “避坑指南”请收好
python·fastapi·web·jwt·oauth2·user·authentication
海鸥-w14 小时前
用python (fastapi)做项目第一天创建项目结构,数据建表,ORM配置安装,写第一个接口
数据库·python·fastapi
li星野16 小时前
从零搭建文件上传系统:FastAPI 后端 + Streamlit 前端
前端·状态模式·fastapi
至天2 天前
FastAPI 接入 FastAPI-Limiter 以及使用 Redis 进行限流指南
redis·python·fastapi·请求限流
li星野2 天前
FastAPI 中间件完全指南:从原理到实战,掌控请求响应的全局钩子
中间件·fastapi
Derrick__12 天前
基于 LangGraph + FastAPI 搭建一个带人工审核的行业分析多智能体系统
ai·agent·fastapi·vibe coding
ss2732 天前
【Python实战】基于FastAPI的绿植养护管理系统 - 完整项目
python·fastapi
li星野2 天前
FastAPI 响应类型完全指南:从 JSON 到流式响应、异常处理与输出模型
前端·json·fastapi
海鸥-w3 天前
python(fastapi) 实现更新,新增,删除接口
android·python·fastapi
我叫张小白。4 天前
Redis BitMap实现用户签到功能
数据库·redis·缓存·fastapi