You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3.11+Pydantic2.5:软件版本校验与缺省字段填充问题

问题描述

使用Python 3.11和Pydantic 2.5搭建数据模型,现有配置数据:

data = {
    'project': 'abc',
    'id': 12345,
    'software': {
        'aaa': {
            'version': '20.1.2.2013',
            'path': '//path_to_software/aaa'
        }, 
        'bbb': {
            'version': '4.0.2',
            'path': '//path_to_software/bbb'
        }, 
        'ccc': {
            'version': '10.0v1',
            'path': '//path_to_software/ccc'
        }
    }
}

对应的现有Pydantic模型:

import pydantic
import pathlib

class SoftwareVersion(pydantic.BaseModel):
    version: str
    path: pathlib.Path

class Software(pydantic.BaseModel):
    aaa: SoftwareVersion
    bbb: SoftwareVersion
    ccc: SoftwareVersion

class Project(pydantic.BaseModel):
    project: str
    id: int
    software: Software

目前模型运行正常,但有两个需求:

  • 为每个软件的version字段做格式校验,无需为每个软件单独创建版本类,希望在SoftwareVersion或Software类中实现校验。
  • 当软件字段(比如ddd)不存在时,自动创建该字段并填充默认值。
解决方案

1. 版本格式校验(在SoftwareVersion类中统一实现)

直接在SoftwareVersion类中给version字段添加校验器,所有引用该类的软件字段都会自动继承校验规则,无需单独为每个软件建类。使用Pydantic的@field_validator装饰器实现:

import pydantic
import pathlib
from pydantic import field_validator
import re

class SoftwareVersion(pydantic.BaseModel):
    version: str
    path: pathlib.Path

    @field_validator('version')
    def validate_version_format(cls, v):
        # 示例正则支持三种版本格式:x.y.z.build、x.y.z、x.yvx
        version_pattern = r'^(?:\d+\.){2}\d+\.\d+$|^(?:\d+\.){2}\d+$|^\d+\.\d+v\d+$'
        if not re.match(version_pattern, v):
            raise ValueError(f"无效的版本格式:{v},支持格式如20.1.2.2013、4.0.2、10.0v1")
        return v

class Software(pydantic.BaseModel):
    aaa: SoftwareVersion
    bbb: SoftwareVersion
    ccc: SoftwareVersion

class Project(pydantic.BaseModel):
    project: str
    id: int
    software: Software

无论aaa、bbb还是其他软件字段,只要使用SoftwareVersion类型,都会自动校验version格式。

2. 自动创建缺失字段并填充默认值

根据软件字段是否固定,提供两种实现方式:

方式一:固定字段直接设置默认值

如果已知所有可能的软件字段,直接在Software类中为每个字段定义默认值:

class Software(pydantic.BaseModel):
    aaa: SoftwareVersion = SoftwareVersion(version='1.0.0', path=pathlib.Path('//default/path/aaa'))
    bbb: SoftwareVersion = SoftwareVersion(version='1.0.0', path=pathlib.Path('//default/path/bbb'))
    ccc: SoftwareVersion = SoftwareVersion(version='1.0.0', path=pathlib.Path('//default/path/ccc'))
    ddd: SoftwareVersion = SoftwareVersion(version='1.0.0', path=pathlib.Path('//default/path/ddd'))

数据中缺少对应字段时,会自动使用定义的默认值。

方式二:动态字段结合模型校验器填充

如果软件字段是动态不确定的,可通过model_config允许额外字段,并使用model_validator自动填充缺失值:

from pydantic import model_validator

class Software(pydantic.BaseModel):
    aaa: SoftwareVersion
    bbb: SoftwareVersion
    ccc: SoftwareVersion

    model_config = {'extra': 'allow'}  # 允许定义外的软件字段

    @model_validator(mode='before')
    def fill_missing_software(cls, values):
        # 定义所有需要默认值的软件字段及默认配置
        default_software = {
            'aaa': {'version': '1.0.0', 'path': '//default/path/aaa'},
            'bbb': {'version': '1.0.0', 'path': '//default/path/bbb'},
            'ccc': {'version': '1.0.0', 'path': '//default/path/ccc'},
            'ddd': {'version': '1.0.0', 'path': '//default/path/ddd'}
        }
        # 合并输入值与默认值,输入值优先级更高
        for key, default_val in default_software.items():
            if key not in values:
                values[key] = default_val
        return values

该方式既自动填充缺失字段的默认值,也支持新增未预先定义的软件字段。

组合方案(同时实现校验与默认值填充)

将上述两种方案结合,完整代码如下:

import pydantic
import pathlib
from pydantic import field_validator, model_validator
import re

class SoftwareVersion(pydantic.BaseModel):
    version: str
    path: pathlib.Path

    @field_validator('version')
    def validate_version_format(cls, v):
        version_pattern = r'^(?:\d+\.){2}\d+\.\d+$|^(?:\d+\.){2}\d+$|^\d+\.\d+v\d+$'
        if not re.match(version_pattern, v):
            raise ValueError(f"无效的版本格式:{v},支持格式如20.1.2.2013、4.0.2、10.0v1")
        return v

class Software(pydantic.BaseModel):
    aaa: SoftwareVersion
    bbb: SoftwareVersion
    ccc: SoftwareVersion

    model_config = {'extra': 'allow'}

    @model_validator(mode='before')
    def fill_missing_software(cls, values):
        default_software = {
            'aaa': {'version': '1.0.0', 'path': '//default/path/aaa'},
            'bbb': {'version': '1.0.0', 'path': '//default/path/bbb'},
            'ccc': {'version': '1.0.0', 'path': '//default/path/ccc'},
            'ddd': {'version': '1.0.0', 'path': '//default/path/ddd'}
        }
        for key, default_val in default_software.items():
            if key not in values:
                values[key] = default_val
        return values

class Project(pydantic.BaseModel):
    project: str
    id: int
    software: Software

# 测试缺失字段场景
test_data = {
    'project': 'abc',
    'id': 12345,
    'software': {
        'aaa': {
            'version': '20.1.2.2013',
            'path': '//path_to_software/aaa'
        }
    }
}

project = Project(**test_data)
print(project.model_dump())
# 输出会包含bbb、ccc、ddd的默认值,且所有version字段均经过格式校验

内容的提问来源于stack exchange,提问作者user1863947

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:40:59