现在位置: 首页 > FastAPI 教程 > 正文

FastAPI Pydantic 模型

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


Pydantic 是什么

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

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

定义 Pydantic 模型

创建一个继承 BaseModel 的类,使用 Python 标准类型声明字段:

实例

from pydantic import BaseModel


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

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

字段声明方式是否必填
namename: str必填
descriptiondescription: str | None = None可选
priceprice: float必填
taxtax: float | None = None可选

使用 Pydantic 模型

作为请求体

最常见的用法是将模型声明为路径操作函数的参数:

实例

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

访问和操作模型数据

实例

@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 实现)。


模型校验示例

当客户端发送的数据不符合模型定义时,FastAPI 会返回详细的校验错误:

实例

# 客户端发送了缺少必填字段的数据
POST /items/
{
    "description": "缺少 name 和 price"
}

# FastAPI 返回校验错误
{
    "detail": [
        {
            "type": "missing",
            "loc": ["body", "name"],
            "msg": "Field required",
            "input": {"description": "缺少 name 和 price"}
        },
        {
            "type": "missing",
            "loc": ["body", "price"],
            "msg": "Field required",
            "input": {"description": "缺少 name 和 price"}
        }
    ]
}

如果发送了类型错误的数据:

// price 应该是数字,但传了字符串
{
    "name": "Foo",
    "price": "not a number"
}

// FastAPI 返回的错误
{
    "detail": [
        {
            "type": "float_parsing",
            "loc": ["body", "price"],
            "msg": "Input should be a valid number, unable to parse string as a number",
            "input": "not a number"
        }
    ]
}

Pydantic v2 常用方法

方法v2(推荐)v1(已弃用)说明
序列化为字典item.model_dump()item.dict()将模型转为 Python 字典
序列化为 JSONitem.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 SchemaItem.model_json_schema()Item.schema()获取模型的 JSON Schema

模型配置(model_config)

Pydantic v2 使用 model_config 替代了 v1 的 Config 内部类:

实例

from pydantic import BaseModel, ConfigDict


class Item(BaseModel):
    name: str
    price: float

    # Pydantic v2 的配置方式
    model_config = ConfigDict(
        json_schema_extra={  # 在 API 文档中显示示例
            "examples": [
                {
                    "name": "Foo",
                    "price": 35.4
                }
            ]
        }
    )

Pydantic v2 中,orm_mode = True 已改为 from_attributes = Trueschema_extra 已改为 json_schema_extraallow_population_by_field_name 已改为 populate_by_name


模型继承

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

实例

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"})}

使用不同的输入和输出模型是保护敏感数据的重要手段。永远不要在 API 响应中返回密码等敏感字段。


小结

Pydantic 模型的核心要点:

  • 使用 BaseModel 定义数据模型,标准 Python 类型声明字段
  • 有默认值的字段可选,没有默认值的字段必填
  • v2 使用 model_dump()model_validate() 等新方法
  • 通过模型继承创建不同的输入/输出模型,保护敏感数据
  • 所有校验和文档都是自动的,只需声明一次类型