Fastapi教程:使用Pydantic定义数据模型

Pydantic 是 FastAPI 的核心组件,用于数据验证和序列化。通过 Pydantic,我们可以轻松定义强类型数据模型,并自动完成数据校验。本文将介绍如何在 FastAPI 中结合 Pydantic 使用,帮助你更高效地构建 API。


什么是 Pydantic?

Pydantic 是一个用于数据验证和数据解析的 Python 库。它基于 Python 的类型注解(type hints)定义数据结构,并在运行时执行验证。Pydantic 能够简化输入验证和数据转换的逻辑,确保数据的正确性和一致性。


安装 Pydantic

FastAPI 默认集成了 Pydantic,因此在安装 FastAPI 后无需单独安装 Pydantic。如果你需要单独安装 Pydantic,可以使用以下命令:

pip install pydantic

使用 Pydantic 定义数据模型

Pydantic 允许我们通过继承 BaseModel 类来定义数据模型。在 FastAPI 中,这些模型用于验证请求体数据,并自动转换为对应的 Python 类型。

示例代码

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

# 定义 Pydantic 数据模型
class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None

@app.post("/items/")
async def create_item(item: Item):
    return {"item": item}

示例解析

  1. 定义数据模型

    • 使用 BaseModel 定义 Item 模型,其中包含 name, description, price, 和 tax 字段。
    • descriptiontax 字段是可选的(使用 None 作为默认值)。
  2. 自动验证
    FastAPI 会根据 Item 模型的定义自动校验请求体中的数据是否符合要求,确保数据类型和约束条件的正确性。

  3. POST 请求
    路由 /items/ 接收 JSON 格式的请求数据,并将其解析为 Item 实例。


测试模型

运行应用后,使用工具(如 Postman 或 cURL)发送 POST 请求:

curl -X POST "http://127.0.0.1:8000/items/" -H "Content-Type: application/json" -d '{"name": "Laptop", "price": 999.99}'

成功响应

{
    "item": {
        "name": "Laptop",
        "description": null,
        "price": 999.99,
        "tax": null
    }
}

错误示例

如果请求数据格式不正确,例如缺少必填字段 name,FastAPI 将返回 422 状态码,并提示错误信息:

{
    "detail": [
        {
            "loc": ["body", "name"],
            "msg": "field required",
            "type": "value_error.missing"
        }
    ]
}

Pydantic 高级特性

1. 默认值与校验

Pydantic 支持通过字段定义默认值,并提供丰富的校验功能。你可以使用 Field 来设置字段的约束和元数据。

from pydantic import BaseModel, Field

class User(BaseModel):
    username: str = Field(..., title="Username", min_length=3, max_length=20)
    age: int = Field(..., ge=18, le=100, description="Age must be between 18 and 100")
  • Field 用于为字段设置额外的校验条件。
  • username 字段的长度限制为 3 到 20。
  • age 字段的值必须在 18 到 100 之间。

2. 嵌套模型

Pydantic 支持嵌套模型,可以通过定义子模型来表示复杂的数据结构。

from pydantic import BaseModel

class Address(BaseModel):
    city: str
    zip_code: str

class User(BaseModel):
    name: str
    address: Address

@app.post("/users/")
async def create_user(user: User):
    return {"user": user}

请求示例:

{
    "name": "Alice",
    "address": {
        "city": "New York",
        "zip_code": "10001"
    }
}

3. 数据转换与校正

Pydantic 自动尝试将输入数据转换为指定类型,这样我们可以避免手动类型转换。

from pydantic import BaseModel

class Item(BaseModel):
    price: float

item = Item(price="19.99")
print(item.price)  # 输出: 19.99 (字符串自动转换为浮点数)

4. 使用 Pydantic @property 格式化日期

在某些情况下,我们希望将日期字段格式化为特定的字符串格式。可以通过 Pydantic 的 @property 装饰器来实现。

from fastapi import FastAPI
from pydantic import BaseModel
from datetime import datetime

app = FastAPI()

class Event(BaseModel):
    name: str
    start_time: datetime

    @property
    def formatted_start_time(self):
        return self.start_time.strftime("%Y-%m-%d %H:%M:%S")

@app.post("/events/")
async def create_event(event: Event):
    return {"event": event, "formatted_start_time": event.formatted_start_time}

示例输出

{
    "event": {
        "name": "Python Workshop",
        "start_time": "2024-12-20T15:00:00"
    },
    "formatted_start_time": "2024-12-20 15:00:00"
}

解析:通过 @property 装饰器将 start_time 格式化为指定的字符串格式。原始的 start_time 仍然是 datetime 类型,格式化后的输出仅在响应中有效。

5. 使用 Pydantic json_encoders 格式化日期

另一种方法是使用 Pydantic 模型的 Config 类中的 json_encoders 配置项,这样可以全局设置日期字段的格式化规则。

from fastapi import FastAPI
from pydantic import BaseModel
from datetime import datetime

app = FastAPI()

class Event(BaseModel):
    name: str
    start_time: datetime

    class Config:
        # 设置 json_encoders 格式化规则
        json_encoders = {
            datetime: lambda v: v.strftime("%Y-%m-%d %H:%M:%S")
        }

@app.post("/events/")
async def create_event(event: Event):
    return {"event": event}

示例输出

{
    "event": {
        "name": "Python Workshop",
        "start_time": "2024-12-20 15:00:00"
    }
}

解析:在 Config 类中,通过 json_encoders 字典设置了全局的 datetime 格式化规则。这样,所有的 datetime 字段都会自动使用该格式进行格式化。


Pydantic 配合依赖注入

FastAPI 支持将 Pydantic 模型与依赖注入结合使用,使得查询参数、路径参数等可以自动解析为 Pydantic 模型。

from fastapi import Depends

class QueryParams(BaseModel):
    q: str
    limit: int = 10

@app.get("/search/")
async def search(params: QueryParams = Depends()):
    return {"query": params.q, "limit": params.limit}

在上述示例中,Depends 会自动将查询参数解析为 QueryParams 对象。


总结

通过本文,我们学习了如何在 FastAPI 中使用 Pydantic,包括:

  • 定义基础数据模型。
  • 验证请求数据并提供详细的错误信息。
  • 使用 Pydantic 的高级功能(嵌套模型、字段约束、自动类型转换等)。
  • 格式化日期输出,并将其与 FastAPI API 响应集成。

为什么选择 Pydantic?

  1. 强大的数据校验:简化输入验证逻辑,确保数据符合预期。
  2. 高效解析与转换:自动进行类型转换和校正。
  3. 现代化的类型支持:基于 Python 的类型注解,代码可读性更高,易于维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值