【Python 基础】FastAPI 响应使用详解

目录

一、前言

[二、 FastAPI 响应介绍与使用](#二、 FastAPI 响应介绍与使用)

[2.1 响应类型](#2.1 响应类型)

[2.2 手动设置响应](#2.2 手动设置响应)

[2.2.1 设置响应类型为Html格式](#2.2.1 设置响应类型为Html格式)

[2.2.2 设置文件类型的响应格式](#2.2.2 设置文件类型的响应格式)

[2.2.3 自定义响应数据格式](#2.2.3 自定义响应数据格式)

[2.3 返回重定向](#2.3 返回重定向)

[2.4 自定义响应头](#2.4 自定义响应头)

[三、FastAPI Pydantic 模型](#三、FastAPI Pydantic 模型)

[3.1 Pydantic 是什么?](#3.1 Pydantic 是什么?)

[3.2 Pydantic 使用](#3.2 Pydantic 使用)

[3.2.1 定义 Pydantic](#3.2.1 定义 Pydantic)

[3.2.2 使用 Pydantic](#3.2.2 使用 Pydantic)

[3.2.3 访问和操作模型数据](#3.2.3 访问和操作模型数据)

四、异常处理

五、写在文末


一、前言

上一篇中,我们详细分享了FastAPI 编写接口中请求以及请求参数相关的使用,本篇将继续分享在FastAPI 框架中,是如何使用响应的,响应也就是接口如何将数据、异常等信息返回给前端,从而让前端更好的处理本次接口的过程。

二、 FastAPI 响应介绍与使用

如下是一次完整的接口请求基本流程,说明了请求和响应的过程

2.1 响应类型

默认情况下,FastAPl会自动将路径操作函数返回的Python 对象(字典、列表、Pydantic模型等),经由jsonable_encoder 转换为JSON兼容格式,并包装为JSONResponse返回。这省去了手动序列化的步骤,让开发者能更专注于业务逻辑。

  • 如果需要返回非 JSON数据(如HTML、文件流),FastAPI提供了丰富的响应类型来返回不同数据

下图中列举了FastAPI中支持的常用返回数据类型

在下面这段基础代码中,我们指定返回了一个jso对象

python 复制代码
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

通过调用接口,在swagger中可以看到,这个返回的数据结构为json类型,而我们在代码中并没有显式定义,框架自动帮我们做了适配

2.2 手动设置响应

一般可以通过下面2种方式进行设置

2.2.1 设置响应类型为Html格式

下面的代码中,设置返回数据类型为Html格式的,只需要在装饰器(请求路径)中增加 设置响应类为HTMLResponse,当前接口即可返回HTML内容,如下代码:

python 复制代码
from fastapi import FastAPI
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.get("/html", response_class=HTMLResponse)
async def get_html():
    return "<h1>Hello World</h1>"

运行服务,请求一下接口,可以看到展示了HTML形式的效果

从Swagger中也可以看出来,响应的是html格式

2.2.2 设置文件类型的响应格式

接口响应文件类型的格式也是日常开发中高频使用的场景,比如一些下载文件的场景,下载PDF,excel等,在这种情况下,可以使用FileResponse这个对象。

FileResponse 是FastAPl提供的专门用于高效返回文件内容(如图片、PDF、Excel、音视频等)的响应类。它能够智能处理文件路径 、媒体类型推断、范围请求和缓存头部,是服务静态文件的推荐方式。

如下代码中,提前在工程目录下准备一个图片,参考下面的代码

python 复制代码
from fastapi import FastAPI
from fastapi.responses import HTMLResponse,FileResponse

app = FastAPI()

@app.get("/html", response_class=HTMLResponse)
async def get_html():
    return "<h1>Hello World</h1>"

@app.get("/file")
async def get_file():
    return FileResponse("./cat.jpeg")

运行服务调用一下接口,可以看到能够在浏览器中直接看到图片文件

2.2.3 自定义响应数据格式

在日常项目开发中,自定义接口的返回数据格式算是最常见的,比如从表中查询了10个字段,前端只需要使用3个字段,此时就可以自定义一个返回数据对象来做。

自定义响应数据格式说明

response_model 是路径操作装饰器(如@app.get或@app.post)的关键参数,它通过一个Pydantic模型来严格定义和约束API端点的输出格式。这一机制在提供自动数据验证和序列化的同时,更是保障数据安全性的第一道防线。

如下代码中,自定义一个Item类,然后在接口路径中使用response_model指定返回的对象为这个Item

python 复制代码
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    id:int
    title:str
    content:str

@app.get("/items/{item_id}",response_model=Item)
async def read_item(id:int):
    return {
        "id": id,
        "title": f"Item {id}",
        "content": "NBA最新新闻"
    }

运行一下调用接口效果如下

使用自定义类对象的返回,各个字段必须都有对应上才可以,如果对应不起来,比如在接口返回的时候少一个字段,如下:

python 复制代码
@app.get("/items/{item_id}",response_model=Item)
async def read_item(id:int):
    return {
        "id": id,
        "title": f"Item {id}"
    }

再次调用的时候会报错

从后台日志中可以看到,意思是返回的数据结构少了一个字段,也就是在这种自定义输出对象的情况下,返回值的结果必须要跟自定义的对象字段对上

2.3 返回重定向

使用RedirectResponse 可以实现重定向的效果,在下面的代码中,使用 RedirectResponse 实现重定向,将客户端重定向到 /items/ 路由

python 复制代码
from fastapi import Header, Cookie
from fastapi import FastAPI
from fastapi.responses import RedirectResponse

app = FastAPI()

@app.get("/items/")
def read_item(user_agent: str = Header(None), session_token: str = Cookie(None)):
    return {"User-Agent": user_agent, "Session-Token": session_token}

@app.get("/redirect")
def redirect():
    return RedirectResponse(url="/items/")

以上代码在浏览器访问 http://127.0.0.1:8000/redirect/ 会自动跳转到 http://127.0.0.1:8000/items/ 页面:

2.4 自定义响应头

在某些场景下,需要将接口返回的数据放在response中,可以使用 JSONResponse 自定义响应头

python 复制代码
from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
    content = {"item_id": item_id}
    headers = {"X-Custom-Header": "custom-header-value"}
    return JSONResponse(content=content, headers=headers)

三、FastAPI Pydantic 模型

Pydantic 是 FastAPI 的核心依赖,用于做数据校验和序列化。它让你使用标准的 Python 类型注解来定义数据模型,自动完成数据校验、类型转换和文档生成。

3.1 Pydantic 是什么?

Pydantic 是一个 Python 数据校验库,它的核心思想是:用 Python 类型注解定义 数据结构 ,Pydantic 自动负责 校验和 转换。在 FastAPI 中,Pydantic 主要作用如下:

|--------|----------------------------|
| 用途 | 说明 |
| 请求体校验 | 自动校验客户端发送的 JSON 数据是否符合模型定义 |
| 响应体序列化 | 将模型数据自动转换为 JSON 响应 |
| 自动文档 | 模型的字段、类型和校验规则自动出现在 API 文档中 |
| 编辑器支持 | 模型属性在编辑器中获得完整的自动补全 |

3.2 Pydantic 使用

3.2.1 定义 Pydantic

创建一个继承 BaseModel 的类,使用 Python 标准类型声明字段,如下代码中自定义了一个Item类,并包含了4个属性,每个属性可以进一步约束

python 复制代码
from pydantic import BaseModel

class Item(BaseModel):
    name: str               # 必填:商品名称
    description: str | None = None  # 可选:商品描述
    price: float            # 必填:商品价格
    tax: float | None = None        # 可选:税费

字段是否必填取决于是否有默认值:

|---------------|----------------------------------|------|
| 字段 | 声明方式 | 是否必填 |
| name | name: str | 必填 |
| description | description: str | None = None | 可选 |
| price | price: float | 必填 |
| tax | tax: float | None = None | 可选 |

3.2.2 使用 Pydantic

最常见的用法是将模型声明为路径操作函数的参数,将其作为请求体

python 复制代码
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

@app.post("/items/")
async def create_item(item: Item):
    # FastAPI 自动校验请求体,校验通过后赋值给 item 参数
    return item

3.2.3 访问和操作模型数据

如下的代码中,可以进一步操作请求对象的参数和数据

python 复制代码
@app.post("/items/")
async def create_item(item: Item):
    # 访问模型属性
    print(item.name)       # 直接访问属性
    print(item.price)      # 编辑器提供自动补全

    # 序列化为字典
    item_dict = item.model_dump()
    print(item_dict)       # {"name": "Foo", "description": None, "price": 45.2, "tax": None}

    # 序列化为 JSON 字符串
    item_json = item.model_dump_json()
    print(item_json)       # '{"name":"Foo","description":null,"price":45.2,"tax":null}'

    return item_dict

通过控制台可以看到相应的输出参数

在上面代码中使用了Pydantic v2 的一些方法,比如使用 model_dump() 和 model_dump_json() 替代了 v1 的 dict() 和 json() 方法。新方法性能更好(底层使用 Rust 实现)。

Pydantic v2 常用方法

|----------------|--------------------------------------|----------------------------|-------------------|
| 方法 | v2(推荐) | v1(已弃用) | 说明 |
| 序列化为字典 | item.model_dump() | item.dict() | 将模型转为 Python 字典 |
| 序列化为 JSON | item.model_dump_json() | item.json() | 将模型转为 JSON 字符串 |
| 从字典创建 | Item.model_validate(data) | Item.parse_obj(data) | 从字典创建并校验模型 |
| 从 JSON 创建 | Item.model_validate_json(json_str) | Item.parse_raw(json_str) | 从 JSON 字符串创建模型 |
| 获取 JSON Schema | Item.model_json_schema() | Item.schema() | 获取模型的 JSON Schema |

Pydantic 模型 继承

Pydantic 模型支持继承,可以方便地创建输入模型和输出模型:

python 复制代码
from pydantic import BaseModel, EmailStr


# 基础模型
class UserBase(BaseModel):
    username: str       # 必填
    email: EmailStr     # 必填,自动校验邮箱格式
    full_name: str | None = None  # 可选


# 创建用户时的输入模型(包含密码)
class UserCreate(UserBase):
    password: str       # 必填


# 返回用户信息时的输出模型(不包含密码)
class UserOut(UserBase):
    id: int             # 由服务器生成


# 使用示例
@app.post("/users/", response_model=UserOut)
async def create_user(user: UserCreate):
    # 函数接收 UserCreate(含密码),但响应使用 UserOut(不含密码)
    # 这样密码就不会出现在 API 响应中
    return {"id": 1, **user.model_dump(exclude={"password"})}

四、异常处理

对于客户端引发的错误(4xx,如资源未找到、认证失败),应使用fastapi.HTTPException来中断正常处理流程,并返回标准错误响应。

通过下面这种自定义异常的写法,可以让客户端在出现问题的时候客户端展示更友好

参考下面的示例代码

python 复制代码
from fastapi import FastAPI, HTTPException

app = FastAPI()


@app.get("/news")
def get_new(id: int):
    ids = [1,2,3,4,5,6]
    if id not in ids:
        raise HTTPException(status_code=404, detail="Item not found")

    return {"item_id": id}

当代码逻辑判定为异常的时候,返回的就是自定义的数据格式

五、写在文末

本篇详细介绍了FastAPI 中接口响应的常用功能,并通过实际案例演示了详细的操作过程,希望对看到的同学有用,本篇到此结束,感谢观看。