5分钟掌握Pydantic

数据模型定义:使用 Python 类来定义数据模型,这些类可以自动将输入转换为 Python 数据类型。

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str

类型检查:Pydantic 强制执行类型检查,确保传入的数据符合模型定义的类型。

user = User(id=1, name='John Doe', email='john.doe@example.com')
# 如果传递错误的类型,比如将id作为字符串,将会引发错误

自动转换:Pydantic 可以将字符串输入自动转换为 Python 原生类型,如 int, float, bool, datetime 等。

class User(BaseModel):
    id: int = Field(..., alias='user_id')  # 使用别名
    email: str

user = User(user_id='123', email='john.doe@example.com')
print(user.id)  # 输出: 123

错误处理:当输入数据不符合模型定义时,Pydantic 提供了详细的错误信息,方便调试。

try:
    User(id='invalid', name='John Doe', email='john.doe@example.com')
except ValidationError as e:
    print(e.json())

配置选项:Pydantic 允许通过配置选项来自定义模型的行为,如是否允许额外字段,是否进行严格的类型检查等。

from pydantic import BaseModel, Extra, Field

# 定义一个模型
class User(BaseModel):
    id: int
    name: str
    email: str
    
    # 内部类 Config 用于设置配置选项
    class Config:
        # 指定如何处理模型中未定义的额外字段
        extra = Extra.allow  # 允许额外字段,它们将被存储在模型的 additional 字典中
        
        # 指定是否允许修改模型实例的属性
        allow_mutation = False  # 不允许修改,使模型实例成为不可变的
        
        # 指定是否将 JSON 字段名作为属性名,而不是 Python 变量名
        alias_generator = lambda x: x  # 使用字段的 JSON 名称作为属性名
        
        # 指定是否将带下划线的属性视为私有
        underscore_attrs_are_private = True  # 将带下划线的属性视为私有
        
        # 指定是否在模型初始化时进行严格的类型检查
        strict_types = True  # 开启严格类型检查
        
        # 指定是否允许使用任意类型作为字段类型
        arbitrary_types_allowed = False  # 不允许任意类型
        
        # 指定是否将枚举的值用作 JSON 序列化
        use_enum_values = True  # 使用枚举值而不是枚举的名称
        
        # 指定 JSON 编码器
        json_encoders = {
            int: lambda x: str(x)  # 为整数定义自定义 JSON 编码器
        }
        
        # 为 JSON Schema 指定额外的字段
        json_schema_extra = {
            'example': {'id': 1, 'name': 'Alice', 'email': 'alice@example.com'}  # 示例数据
        }

泛型模型:支持泛型模型,可以创建基于泛型的复杂数据结构。

from typing import List, Dict

class ModelGenerics(BaseModel):
    data: List[str]
    config: Dict[str, str]

data = ModelGenerics(data=['item1', 'item2'], config={'key': 'value'})

在 Python 3.5 中引入,作为对泛型的支持。

在 Python 的 typing 模块中,Optional 和 Union 是两个非常有用的类型注解工具,它们经常一起使用来表达某些类型上的需求。

Optional

Optional 是一个用于表示某个类型的值可能存在,也可能是 None 的类型注解。它通常用于函数注解中,来表明一个参数可以被省略(默认为 None),或者一个变量可能有值或没有值。

Union

Union 是一个类型注解工具,它允许一个变量可以是多种类型中的一种。它使用圆括号 () 来包裹多个类型,表示变量可以是这些类型中的任何一个。

Optional[Union[int, str]]

当你看到 Optional[Union[int, str]] 这样的类型注解时,它的意思是:

  • 这个注解表示的变量可以接受以下三种情况之一:
    1. 一个整数 (int)
    2. 一个字符串 (str)
    3. 没有值,即 None

在函数注解中,这通常表示一个参数可以是整数、字符串或者完全不传(默认为 None)。
下面是一个使用 Optional[Union[int, str]] 的例子:

from typing import Optional, Union

def process_value(value: Optional[Union[int, str]]) -> str:
    if value is None:
        return "No value provided"
    elif isinstance(value, int):
        return f"The value is an integer: {value}"
    elif isinstance(value, str):
        return f"The value is a string: {value}"
    else:
        return "Unknown type"

Callable
在 Python 中,Callable 是 typing 模块提供的一个泛型类型,用于注解函数对象。当你想要定义一个变量、参数或者返回值必须是一个函数时,可以使用 Callable。
Callable 的使用格式如下:

Callable[[arg1_type, arg2_type, ..., argN_type], return_type]
  • arg1_type, arg2_type, …, argN_type 是函数参数的类型。
  • return_type 是函数返回值的类型。

JSON 支持:Pydantic 可以轻松地将模型序列化为 JSON,也可以从 JSON 反序列化模型。

序列化为 JSON

user = User(id=1, name='John Doe', email='john.doe@example.com')
user_json = user.json()  # 序列化为JSON字符串
print(user_json)

JSON 反序列化模型

'{
  "id": 1,
  "name": "John Doe",
  "email": "john.doe@example.com"
}'

user_json = '''
{
  "id": 1,
  "name": "John Doe",
  "email": "john.doe@example.com"
}
'''

user = User.parse_raw(user_json)
print(user)
print(user.id, user.name, user.email)

环境变量加载:Pydantic 可以自动从环境变量中加载配置。

from pydantic import BaseSettings

# 定义一个继承自 BaseSettings 的 Settings 类
class Settings(BaseSettings):
    # 定义一个名为 DEBUG 的布尔类型配置项,并设置默认值为 False
    DEBUG: bool = False
    # 定义一个名为 DB_USER 的字符串类型配置项,没有默认值,需要从环境变量或其它方式提供
    DB_USER: str
    # 定义一个名为 DB_PASSWORD 的字符串类型配置项,同样需要外部提供
    DB_PASSWORD: str

# 创建 Settings 类的实例
settings = Settings()

# 打印 DEBUG 配置项的值,由于没有指定环境变量或其它赋值方式,将输出默认值 False
print(settings.DEBUG)

# 尝试打印 DB_USER 配置项的值
# 如果没有通过环境变量或其它方式提供 DB_USER 的值,这将抛出一个错误,因为没有默认值
print(settings.DB_USER)

字段校验:提供了多种字段校验器,用于验证数据的有效性,如长度、正则表达式匹配等。

from pydantic import BaseModel, Field, validator
from typing import List

class User(BaseModel):
    name: str
    email: str
    passwords: List[str] = Field(..., min_items=2)

    @validator('email')
    def email_must_contain_at(cls, v):
        if '@' not in v:
            raise ValueError('must contain @')
        return v

user = User(name='John', email='john.doe', passwords=['pass1', 'pass2'])

pydantic 与JSON Schema 关系与关系

JSON Schema 是一种基于 JSON 格式的声明性语言,用于描述和验证 JSON 数据结构。它最初由 JSON 的创建者 Douglas Crockford 提出概念,并由一个社区驱动的进程进一步开发和标准化。JSON Schema 的目的是为了让 JSON 数据能够自我描述,即包含足够的元数据来描述其自身的结构,从而允许自动化的验证和编辑。

JSON Schema 的主要用途包括:

  1. 数据验证:确保 JSON 数据符合预定义的模式,比如检查数据类型、格式、长度等。
  2. 自动化测试:自动化测试工具可以使用 JSON Schema 来验证 API 返回的数据是否符合预期。
  3. API 文档:作为 API 文档的一部分,帮助开发者理解 API 请求和响应的数据结构。
  4. 配置管理:用于定义配置文件的结构,确保配置文件中的设置是有效和合理的。
  5. 用户界面生成:基于 JSON Schema 自动生成表单和用户界面,以输入和编辑数据。
  6. 数据交换:作为不同系统或组件之间交换数据时的契约,确保数据的兼容性。

JSON Schema 被广泛应用于各种编程语言和环境中,是现代软件开发中数据验证和描述的重要工具之一。随着 JSON 格式的普及,JSON Schema 也成为了描述 JSON 数据的事实标准之一。

要将 Pydantic 模型转换为 JSON Schema,你可以使用模型的 schema() 方法。下面是一个示例:

from pydantic import BaseModel, Field

class User(BaseModel):
    id: int
    name: str
    email: str
    
    # 定义一个字段的额外信息,比如示例值
    email = Field(..., example='user@example.com')

# 获取 JSON Schema 表示
schema = User.schema()

print(schema)

运行上述代码会输出类似于下面的 JSON Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string",
      "format": "email"
    }
  },
  "required": [
    "id",
    "name",
    "email"
  ],
  "example": {
    "id": 0,
    "name": "",
    "email": "user@example.com"
  }
}

请注意,输出的 JSON Schema 包含了模型的所有字段,它们的类型,以及是否是必须的。此外,如果字段使用了 Field 函数来定义额外的元数据(如示例值),这些信息也会被包含在内。

JSON Schema 可以用于各种用途,包括:

  • 自动化测试:验证输入数据是否符合预期的模型。
  • API 文档:为 API 提供正式的、可机器读取的文档。
  • 代码生成:基于 JSON Schema 自动生成代码,如客户端库或服务端存根。
  • 交互式表单:基于 JSON Schema 自动生成表单界面。

Pydantic 的 schema() 方法是一个非常强大的工具,可以帮助你将 Python 模型定义转换为一个广泛接受的、标准化的格式。

Pydantic 支持嵌套模型,这意味着你可以在一个 Pydantic 模型中定义另一个 Pydantic 模型作为其字段之一。这使得你可以创建复杂的数据结构,如对象包含对象,或者对象包含数组等。

嵌套模型示例

假设我们有一个博客系统,需要定义 PostUser 两个模型,其中 Post 模型嵌套了 User 模型:

from pydantic import BaseModel

class User(BaseModel):
    name: str
    email: str

class Post(BaseModel):
    title: str
    content: str
    author: User  # 这里 Post 嵌套了 User 模型作为其字段
    published: bool = False

# 创建 Post 实例
post = Post(
    title='Pydantic 嵌套模型',
    content='Pydantic 是多么方便啊!',
    author=User(name='Alice', email='alice@example.com'),
    published=True
)

print(post)

在这个例子中:

  • User 是一个包含 nameemail 字段的 Pydantic 模型。
  • Post 是另一个 Pydantic 模型,它有一个 author 字段,该字段的类型是 User。这样,Post 模型就嵌套了 User 模型。
  • 创建 Post 实例时,你需要为 author 字段提供一个 User 实例。

嵌套模型的 JSON Schema

当你为嵌套的 Pydantic 模型生成 JSON Schema 时,Pydantic 会自动处理这些嵌套关系,生成相应的 schema:

print(Post.schema())

这将输出一个包含 PostUser 模型的 JSON Schema,其中 Postauthor 字段会链接到 User 的 schema。

嵌套模型的序列化和反序列化

Pydantic 同样支持嵌套模型的序列化(将模型实例转换为 JSON)和反序列化(从 JSON 创建模型实例):

# 序列化 Post 实例为 JSON
post_json = post.json()
print(post_json)

# 假设有一段 JSON 字符串表示 Post
post_json_str = '''
{
  "title": "Pydantic 嵌套模型",
  "content": "Pydantic 是多么方便啊!",
  "author": {
    "name": "Alice",
    "email": "alice@example.com"
  },
  "published": true
}
'''

# 反序列化 JSON 字符串为 Post 实例
post_from_json = Post.parse_raw(post_json_str)
print(post_from_json)

通过嵌套模型,Pydantic 提供了一种强大的方式来处理复杂的数据结构,同时保持了序列化和反序列化的便利性。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值