Python中Pydantic的主要用法小结

 更新时间:2026年04月01日 11:07:50   作者:丁当粑粑  
本文主要介绍了Pydantic的主要用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Pydantic 是一个基于 Python 类型注解的数据验证和设置管理库,它通过定义数据模型自动验证数据类型和格式,同时支持类型转换、序列化、错误处理及配置管理。

1. 基础模型定义

from pydantic import BaseModel
from datetime import datetime
from typing import Optional, List
class User(BaseModel):
    id: int
    name: str
    email: str
    age: Optional[int] = None
    created_at: datetime = datetime.now()
# 创建实例
user = User(id=1, name="张三", email="zhangsan@example.com")
print(user)
# 输出: id=1 name='张三' email='zhangsan@example.com' age=None created_at=datetime.datetime(...)
# 访问属性
print(user.name)  # 张三
print(user.model_dump())  # 转换为字典

2. 数据验证

from pydantic import BaseModel, Field, ValidationError, EmailStr
class User(BaseModel):
    name: str = Field(..., min_length=2, max_length=50, description="用户名")
    age: int = Field(..., ge=0, le=150, description="年龄")
    email: EmailStr  # 自动验证邮箱格式
try:
    # 无效数据
    user = User(name="A", age=200, email="invalid-email")
except ValidationError as e:
    print(e.json())
    # 输出详细的验证错误信息

3. 嵌套模型

from pydantic import BaseModel
from typing import List
class Address(BaseModel):
    street: str
    city: str
    zipcode: str
class User(BaseModel):
    name: str
    age: int
    address: Address
    tags: List[str] = []
# 创建嵌套对象
user = User(
    name="李四",
    age=25,
    address={"street": "中山路123号", "city": "北京", "zipcode": "100000"},
    tags=["python", "developer"]
)
print(user.address.city)  # 北京

4. 自定义验证器

from pydantic import BaseModel, validator, field_validator
class Product(BaseModel):
    name: str
    price: float
    discount: float = 0.0
    @field_validator('price')
    def price_must_be_positive(cls, v):
        if v <= 0:
            raise ValueError('价格必须大于0')
        return v
    @field_validator('discount')
    def discount_valid(cls, v, info):
        if v < 0 or v > 1:
            raise ValueError('折扣必须在0-1之间')
        return v
    @property
    def final_price(self) -> float:
        """计算最终价格"""
        return self.price * (1 - self.discount)
# 使用
product = Product(name="笔记本电脑", price=5999.99, discount=0.1)
print(product.final_price)  # 5399.991

5. 数据转换

from pydantic import BaseModel
from datetime import date
class Event(BaseModel):
    name: str
    date: date  # 自动将字符串转换为date对象
    attendees: int
# 从字典创建
data = {
    "name": "Python会议",
    "date": "2024-12-25",
    "attendees": "100"  # 字符串会自动转换为int
}
event = Event(**data)
print(event.date)  # 2024-12-25 (date对象)
print(type(event.attendees))  # <class 'int'>

6. 配置和序列化

from pydantic import BaseModel
from datetime import datetime
class User(BaseModel):
    id: int
    name: str
    password: str
    class Config:
        # 从ORM对象创建
        from_attributes = True
        # 自定义字段名
        alias_generator = lambda field: field.upper()
        # 排除某些字段
        fields = {'password': {'exclude': True}}
# 序列化时排除密码
user = User(id=1, name="王五", password="secret123")
print(user.model_dump())  # {'id': 1, 'name': '王五'}

7. 泛型支持

from pydantic import BaseModel
from typing import Generic, TypeVar, List
T = TypeVar('T')
class APIResponse(BaseModel, Generic[T]):
    code: int
    message: str
    data: T
# 使用
class User(BaseModel):
    id: int
    name: str
# 单个用户响应
response = APIResponse[User](
    code=200,
    message="success",
    data={"id": 1, "name": "张三"}
)
# 用户列表响应
response_list = APIResponse[List[User]](
    code=200,
    message="success",
    data=[{"id": 1, "name": "张三"}, {"id": 2, "name": "李四"}]
)

8. 实际应用场景:FastAPI集成

from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class UserCreate(BaseModel):
    username: str = Field(..., min_length=3, max_length=20)
    email: str
    password: str = Field(..., min_length=8)
@app.post("/users/")
async def create_user(user: UserCreate):
    # 自动验证请求数据
    return {"message": f"用户 {user.username} 创建成功"}

9. 高级特性:递归模型

from pydantic import BaseModel
from typing import List, Optional
class Category(BaseModel):
    id: int
    name: str
    children: List['Category'] = []  # 自引用
    class Config:
        # 允许自引用
        arbitrary_types_allowed = True
# 创建树形结构
root = Category(
    id=1,
    name="电子产品",
    children=[
        Category(id=2, name="手机", children=[]),
        Category(id=3, name="电脑", children=[
            Category(id=4, name="笔记本", children=[]),
            Category(id=5, name="台式机", children=[])
        ])
    ]
)

10. 环境变量支持

from pydantic_settings import BaseSettings
from typing import Optional
class Settings(BaseSettings):
    app_name: str = "MyApp"
    database_url: str
    debug: bool = False
    api_key: Optional[str] = None
    class Config:
        env_file = ".env"  # 从.env文件读取环境变量
# 使用
settings = Settings()
print(settings.database_url)  # 从环境变量或.env文件读取

Pydantic的主要优势:

  1. 类型安全:自动进行类型检查和转换
  2. 数据验证:丰富的验证器
  3. IDE友好:完整的类型提示支持
  4. 性能优异:基于Python类型提示,性能好
  5. 易于集成:与FastAPI等框架无缝集成

这些例子展示了Pydantic的主要特性,实际开发中可以根据需求灵活使用。

我来详细解释第6部分的"配置和序列化"代码:

Config基础概念

在Pydantic中,Config类是用来配置模型行为的特殊内部类。

1. 基本模型

from pydantic import BaseModel
from datetime import datetime

class User(BaseModel):
    id: int
    name: str
    password: str
    
# 创建用户
user = User(id=1, name="王五", password="secret123")

# 默认序列化:所有字段都会输出
print(user.model_dump())  
# 输出: {'id': 1, 'name': '王五', 'password': 'secret123'}

2. 添加Config配置

class User(BaseModel):
    id: int
    name: str
    password: str
    
    class Config:
        # 1. from_attributes = True
        from_attributes = True
        
        # 2. alias_generator = lambda field: field.upper()
        alias_generator = lambda field: field.upper()
        
        # 3. fields = {'password': {'exclude': True}}
        fields = {'password': {'exclude': True}}

现在我来详细解释每个配置项:

配置1:from_attributes = True

这个配置允许从其他对象创建Pydantic模型实例,比如从数据库ORM对象:

# 假设有一个SQLAlchemy的User模型
class SQLAlchemyUser:
    def __init__(self, id, name, password):
        self.id = id
        self.name = name
        self.password = password

# 创建ORM对象
db_user = SQLAlchemyUser(id=1, name="赵六", password="pass456")

# 没有from_attributes = True时,这样会报错
# user = User.model_validate(db_user)  # 错误!

# 有了from_attributes = True,就可以直接从ORM对象创建
user = User.model_validate(db_user)  # 正确!
print(user.name)  # 输出: 赵六

实际应用场景

# 从数据库查询出来的对象
db_user = db.query(User).first()  # 这是一个SQLAlchemy对象
# 直接转换为Pydantic模型用于API响应
pydantic_user = User.model_validate(db_user)

配置2:alias_generator = lambda field: field.upper()

这个配置定义了字段别名生成规则。upper()表示将字段名转换为大写:

class User(BaseModel):
    id: int
    name: str
    password: str
    
    class Config:
        alias_generator = lambda field: field.upper()

# 创建对象时可以使用大写字段名
user = User(ID=1, NAME="王五", PASSWORD="secret123")
# 虽然字段名是小写的,但可以用大写传入

print(user.id)      # 1
print(user.name)    # 王五

# 序列化时也会使用别名
print(user.model_dump(by_alias=True))  
# 输出: {'ID': 1, 'NAME': '王五', 'PASSWORD': 'secret123'}

print(user.model_dump())  
# 输出: {'id': 1, 'name': '王五', 'password': 'secret123'}  # 默认还是原字段名

实际应用场景:处理不同命名规范的API(例如,Python使用小写,但API使用大写或驼峰)

# 处理使用驼峰命名的API
class User(BaseModel):
    user_id: int
    user_name: str
    
    class Config:
        alias_generator = lambda field: ''.join(
            word.capitalize() if i > 0 else word 
            for i, word in enumerate(field.split('_'))
        )  # 转换为驼峰: user_name -> userName

# 现在可以接收驼峰格式的数据
user = User(userId=1, userName="张三")  # 使用驼峰

配置3:fields = {'password': {'exclude': True}}

这个配置指定在序列化时排除某些字段:

class User(BaseModel):
    id: int
    name: str
    password: str
    
    class Config:
        fields = {'password': {'exclude': True}}

user = User(id=1, name="王五", password="secret123")

# 序列化时自动排除password字段
print(user.model_dump())  
# 输出: {'id': 1, 'name': '王五'}
# 注意:password被排除了

# 即使想包含password也包含不了
print(user.model_dump(exclude={'password': False}))  # 依然没有password

完整示例对比

from pydantic import BaseModel
# 无配置版本
class UserSimple(BaseModel):
    id: int
    name: str
    password: str
# 完整配置版本
class UserConfigured(BaseModel):
    id: int
    name: str
    password: str
    class Config:
        from_attributes = True
        alias_generator = lambda field: field.upper()
        fields = {'password': {'exclude': True}}
# 演示对比
print("=== 简单版本 ===")
user1 = UserSimple(id=1, name="张三", password="123")
print(user1.model_dump())  # {'id': 1, 'name': '张三', 'password': '123'}
print("\n=== 配置版本 ===")
# 1. 可以使用大写别名
user2 = UserConfigured(ID=1, NAME="李四", PASSWORD="456")
print(user2.name)  # 李四
# 2. 序列化时排除password
print(user2.model_dump())  # {'id': 1, 'name': '李四'}
# 3. 可以输出带别名的版本
print(user2.model_dump(by_alias=True))  # {'ID': 1, 'NAME': '李四'}
print("\n=== 从ORM对象创建 ===")
class ORMUser:
    def __init__(self, id, name, password):
        self.id = id
        self.name = name
        self.password = password
# 从ORM对象直接创建
orm_user = ORMUser(id=3, name="王五", password="789")
pydantic_user = UserConfigured.model_validate(orm_user)
print(pydantic_user.model_dump())  # {'id': 3, 'name': '王五'}
# password字段被自动排除

其他常用Config配置

class User(BaseModel):
    id: int
    name: str
    email: str
    
    class Config:
        # 1. 允许额外字段
        extra = "allow"  # 或 "forbid"(禁止)或 "ignore"(忽略)
        
        # 2. 设置JSON编码器
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }
        
        # 3. 验证赋值
        validate_assignment = True  # 赋值时重新验证
        
        # 4. 标题
        title = "User Model"

总结

这个示例展示了Pydantic的三个重要配置:

  1. from_attributes = True:让模型可以从其他Python对象(如数据库ORM对象)创建
  2. alias_generator:自动生成字段别名,用于处理不同命名规范的输入输出
  3. fields = {'password': {'exclude': True}}:永久排除敏感字段(如密码),防止意外泄露

这些配置让Pydantic模型更加灵活和安全,特别适合在实际项目中使用。

到此这篇关于Python中Pydantic的主要用法小结的文章就介绍到这了,更多相关Pydantic 用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python读取MRI并显示为灰度图像实例代码

    Python读取MRI并显示为灰度图像实例代码

    这篇文章主要介绍了Python读取MRI并显示为灰度图像实例代码,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • python基础教程之Hello World!

    python基础教程之Hello World!

    这篇文章主要介绍了python基础教程之Hello World!,本文讲解了命令行中、文件中、脚本文件中输出Hello World的例子,需要的朋友可以参考下
    2014-08-08
  • Python列表和数组的深入解析与最佳选择指南

    Python列表和数组的深入解析与最佳选择指南

    在Python的编程世界中,数据结构犹如画家手中的调色板,而列表(List)和数组(Array)则是其中最常用的两种颜色,它们看似相似,实则各具特色,本文将带您深入探索这两种数据结构的奥秘,助您在编程实践中做出明智选择,需要的朋友可以参考下
    2026-02-02
  • Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释

    Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释

    如何利用Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释等操作下面就为大家介绍一下
    2020-01-01
  • Python图片文字识别与提取实战记录

    Python图片文字识别与提取实战记录

    这篇文章主要介绍了Python图片文字识别与提取的相关资料,本文介绍了如何安装和配置OCR环境,包括安装pytesseract扩展包、窗口配套软件以及配置环境变量,在完成环境搭建后,即可进行图片中文字的提取,需要的朋友可以参考下
    2024-09-09
  • Python装饰器与线程结合提高接口访问效率方法

    Python装饰器与线程结合提高接口访问效率方法

    这篇文章主要为大家介绍了如何实现Python装饰器与线程结合来提高接口的访问效率,有需要的朋友可以借鉴参考下,希望可以有所帮助
    2021-09-09
  • Tensorflow中的图(tf.Graph)和会话(tf.Session)的实现

    Tensorflow中的图(tf.Graph)和会话(tf.Session)的实现

    这篇文章主要介绍了Tensorflow中的图(tf.Graph)和会话(tf.Session)的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • python数据可视化之条形图画法

    python数据可视化之条形图画法

    这篇文章主要为大家详细介绍了python数据可视化之条形图画法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 关于pandas的离散化,面元划分详解

    关于pandas的离散化,面元划分详解

    今天小编就为大家分享一篇关于pandas的离散化,面元划分详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • Python中sys模块功能与用法实例详解

    Python中sys模块功能与用法实例详解

    这篇文章主要介绍了Python中sys模块功能与用法,结合实例形式详细分析了Python sys模块基本功能、原理、使用方法及操作注意事项,需要的朋友可以参考下
    2020-02-02

最新评论