在使用Pydantic构建数据模型时,我们经常需要给字段添加长度约束,其中max_length是最常用的约束之一。但有些场景下,我们需要通过代码动态获取这些约束规则,而不是手动写死数值。下面我们就来详细讲解具体的实现方式。

Pydantic V1版本的实现方式
在Pydantic V1版本中,模型的字段信息存储在__fields__属性中,每个字段的约束参数都放在field_info的extra或者max_length属性里。我们可以通过下面的步骤获取max_length值:
- 先获取目标模型的字段字典
- 找到对应字段的
field_info对象 - 从
field_info中读取max_length属性
下面是完整的代码示例:
from pydantic import BaseModel, Field
# 定义带max_length约束的Pydantic V1模型
class UserV1(BaseModel):
name: str = Field(..., max_length=10, description="用户名称")
desc: str = Field(None, max_length=50, description="用户描述")
def get_max_length_v1(model_cls, field_name):
# 获取模型的字段字典
fields = model_cls.__fields__
if field_name not in fields:
raise ValueError(f"字段{field_name}不存在于模型{model_cls.__name__}中")
# 获取字段的field_info
field_info = fields[field_name].field_info
# 返回max_length值,如果没有设置则返回None
return getattr(field_info, 'max_length', None)
# 测试获取name字段的max_length
name_max_len = get_max_length_v1(UserV1, "name")
print(f"UserV1模型name字段的max_length值:{name_max_len}")
# 测试获取desc字段的max_length
desc_max_len = get_max_length_v1(UserV1, "desc")
print(f"UserV1模型desc字段的max_length值:{desc_max_len}")
# 测试没有设置max_length的字段
class TestModelV1(BaseModel):
age: int
test_max_len = get_max_length_v1(TestModelV1, "age")
print(f"TestModelV1模型age字段的max_length值:{test_max_len}")Pydantic V2版本的实现方式
Pydantic V2版本对内部结构做了调整,字段信息改为了model_fields属性,约束参数也统一放在field_info的metadata中,其中max_length属于Length类型的元数据。我们需要遍历metadata找到对应的长度约束:
from pydantic import BaseModel, Field
from pydantic_core import core_schema
# 定义带max_length约束的Pydantic V2模型
class UserV2(BaseModel):
name: str = Field(..., max_length=10, description="用户名称")
desc: str = Field(None, max_length=50, description="用户描述")
def get_max_length_v2(model_cls, field_name):
# 获取模型的字段字典
fields = model_cls.model_fields
if field_name not in fields:
raise ValueError(f"字段{field_name}不存在于模型{model_cls.__name__}中")
# 获取字段的field_info
field_info = fields[field_name]
# 遍历metadata找到Length类型的约束
if field_info.metadata:
for meta in field_info.metadata:
# 判断是否是长度约束的metadata
if isinstance(meta, core_schema.Length):
return meta.max_length
return None
# 测试获取name字段的max_length
name_max_len = get_max_length_v2(UserV2, "name")
print(f"UserV2模型name字段的max_length值:{name_max_len}")
# 测试获取desc字段的max_length
desc_max_len = get_max_length_v2(UserV2, "desc")
print(f"UserV2模型desc字段的max_length值:{desc_max_len}")
# 测试没有设置max_length的字段
class TestModelV2(BaseModel):
age: int
test_max_len = get_max_length_v2(TestModelV2, "age")
print(f"TestModelV2模型age字段的max_length值:{test_max_len}")通用兼容方案
如果项目中同时存在V1和V2版本的Pydantic,可以通过以下方式做兼容处理:
import pydantic
def get_max_length_compat(model_cls, field_name):
# 判断Pydantic版本
if pydantic.VERSION.startswith('1.'):
# V1版本逻辑
fields = model_cls.__fields__
if field_name not in fields:
raise ValueError(f"字段{field_name}不存在于模型{model_cls.__name__}中")
field_info = fields[field_name].field_info
return getattr(field_info, 'max_length', None)
else:
# V2版本逻辑
from pydantic_core import core_schema
fields = model_cls.model_fields
if field_name not in fields:
raise ValueError(f"字段{field_name}不存在于模型{model_cls.__name__}中")
field_info = fields[field_name]
if field_info.metadata:
for meta in field_info.metadata:
if isinstance(meta, core_schema.Length):
return meta.max_length
return None
# 测试兼容方法
if pydantic.VERSION.startswith('1.'):
from pydantic import BaseModel, Field
class CompatModel(BaseModel):
title: str = Field(..., max_length=20)
else:
from pydantic import BaseModel, Field
class CompatModel(BaseModel):
title: str = Field(..., max_length=20)
title_max_len = get_max_length_compat(CompatModel, "title")
print(f"兼容方案获取title字段的max_length值:{title_max_len}")注意事项
- 如果字段没有设置max_length约束,上述方法都会返回None,使用时需要做判空处理
- 只有字符串、列表等支持长度约束的字段才会存在max_length属性,数值类型等其他字段设置该参数会直接报错
- V2版本中的
Length元数据同时包含min_length和max_length,如果需要获取最小长度可以同样通过该对象获取
Pydanticmax_length模型字段字段约束修改时间:2026-05-28 22:11:35