模型配置
pydantic 的行为可以通过模型上的 Config
类或 pydantic 数据类来控制。
from pydantic import BaseModel, ValidationError
class Model(BaseModel):
v: str
class Config:
max_anystr_length = 10
error_msg_templates = {
'value_error.any_str.max_length': 'max_length:{limit_value}',
}
try:
Model(v='x' * 20)
except ValidationError as e:
print(e)
"""
1 validation error for Model
v
max_length:10 (type=value_error.any_str.max_length; limit_value=10)
"""
(这个脚本是完整的,它应该“按原样”运行)
此外,您可以将配置选项指定为模型类 kwargs:
from pydantic import BaseModel, ValidationError, Extra
class Model(BaseModel, extra=Extra.forbid):
a: str
try:
Model(a='spam', b='oh no')
except ValidationError as e:
print(e)
"""
1 validation error for Model
b
extra fields not permitted (type=value_error.extra)
"""
(这个脚本是完整的,它应该“按原样”运行)
同样,如果使用@dataclass
装饰器:
from datetime import datetime
from pydantic import ValidationError
from pydantic.dataclasses import dataclass
class MyConfig:
max_anystr_length = 10
validate_assignment = True
error_msg_templates = {
'value_error.any_str.max_length': 'max_length:{limit_value}',
}
@dataclass(config=MyConfig)
class User:
id: int
name: str = 'John Doe'
signup_ts: datetime = None
user = User(id='42', signup_ts='2032-06-21T12:00')
try:
user.name = 'x' * 20
except ValidationError as e:
print(e)
"""
1 validation error for User
name
max_length:10 (type=value_error.any_str.max_length; limit_value=10)
"""
(这个脚本是完整的,它应该“按原样”运行)
可选项(Options)¶
title
- 生成的 JSON 模式的标题
anystr_strip_whitespace
- 是否去除 str & byte 类型的前导和尾随空格(默认值:
False
) anystr_upper
- 是否将 str 和 byte 类型的所有字符都设为大写(默认值:
False
) anystr_lower
- 是否将 str 和 byte 类型的所有字符都设为小写(默认值:
False
) min_anystr_length
- str 和 byte 类型的最小长度(默认值:
0
) max_anystr_length
- str & byte 类型的最大长度(默认值:
None
) validate_all
- 是否验证字段默认值(默认值:
False
) extra
- 在模型初始化期间是否忽略、允许或禁止额外的属性。 接受
“ignore”
、“allow”
或“forbid”
的字符串值,或“Extra”
枚举的值(默认值:“Extra.ignore”
)。 如果包含额外的属性,'forbid'
将导致验证失败,'ignore'
将默默地忽略任何额外的属性,'allow'
将属性分配给模型。 allow_mutation
- 模型是否是伪不可变的,即是否允许
__setattr__
(默认值:True
)
frozen
Warning
此参数处于测试阶段
- 设置
frozen=True
会执行allow_mutation=False
所做的一切,还会为模型生成__hash__()
方法。 如果所有属性都是可散列的,这使得模型的实例可能是可散列的。 (默认值:False
) use_enum_values
- 是否使用枚举的
value
属性而不是原始枚举来填充模型。 如果您想稍后序列化model.dict()
(默认值:False
),这可能很有用 fields
- 包含每个字段的架构信息的
dict
; 这等同于使用Field
类,除非已经通过注释或 Field 类定义了一个字段,在这种情况下只有alias
、include
、exclude
、min_length
,max_length
,regex
,gt
,lt
,gt
,le
,multiple_of
,max_digits
,decimal_places
,min_items
,max_items
,unique_items
和allow_mutation
可以设置(例如你不能设置default_factory
的默认值)(默认值:None
) validate_assignment
- 是否对属性的
_assignment_
执行验证(默认值:False
) allow_population_by_field_name
- 别名字段是否可以由模型属性给出的名称以及别名(默认值:
False
)填充
Note
此配置设置的名称在 v1.0 中从allow_population_by_alias
更改为allow_population_by_field_name
。
error_msg_templates
- 用于覆盖默认错误消息模板的
dict
。 传入一个字典,其中的键与您要覆盖的错误消息匹配(默认值:{}
) arbitrary_types_allowed
- 是否允许字段的任意用户类型(通过检查值是否是该类型的实例来验证它们)。 如果为
False
,将在模型声明时引发RuntimeError
(默认值:False
)。 请参阅 Field Types 中的示例。 orm_mode
- 是否允许使用 ORM 模式
getter_dict
- 在分解任意类进行验证时使用的自定义类(应继承自
GetterDict
),与orm_mode
一起使用; 参见 数据绑定。 alias_generator
- 一个可调用的,它接受一个字段名并为其返回一个别名; 参见 专用部分
keep_untouched
- 模型默认值的类型元组(例如描述符),在模型创建期间不应更改并且不会包含在模型模式中。 注意:这意味着模型上具有 这种类型的默认值 而不是 这种类型的注释 的属性将被单独保留。
schema_extra
- 用于扩展/更新生成的 JSON Schema 的
dict
,或用于对其进行后处理的可调用对象; 参见 schema 自定义 json_loads
- 用于解码 JSON 的自定义函数; 参见 自定义 JSON(反)序列化
json_dumps
- 用于编码 JSON 的自定义函数; 参见 自定义 JSON(反)序列化
json_encoders
- 用于自定义类型编码为 JSON 的方式的
dict
; 参见 JSON 序列化 underscore_attrs_are_private
- 是否将任何下划线非类属性视为私有,或保持原样; 参见 私有模型属性
copy_on_model_validation
- 字符串文字来控制模型实例在验证过程中的处理方式,使用以下方法(有关此字段更改的完整讨论,请参阅 #4093 :
'none'
- 模型不会在验证时被复制,它们只是保持“不变(untouched)”'shallow'
- 模型是浅拷贝的,这是默认的'deep'
- 模型被深度复制
smart_union
- pydantic 是否应该尝试检查
Union
中的所有类型以防止不希望的强制转换; 请参阅 专用部分 post_init_call
- stdlib 数据类
__post_init__
是否应该在解析和验证之前(默认行为值为'before_validation'
)或之后(值为'after_validation'
)运行转换。 allow_inf_nan
- 是否允许无穷大(
+inf
和-inf
)和 NaN 值浮动字段,默认为True
,设置为False
以兼容JSON
,参见[#3994](https:// github.com/pydantic/pydantic/pull/3994)了解更多详情,添加于V1.10
全局改变行为(Change behaviour globally)¶
如果您希望全局更改 pydantic 的行为,您可以使用自定义 Config
创建自己的自定义 BaseModel
,因为配置是继承的
from pydantic import BaseModel as PydanticBaseModel
class BaseModel(PydanticBaseModel):
class Config:
arbitrary_types_allowed = True
class MyClass:
"""A random class"""
class Model(BaseModel):
x: MyClass
(这个脚本是完整的,它应该“按原样”运行)
别名生成器(Alias Generator)¶
如果数据源字段名称与您的代码风格不匹配(例如 CamelCase 字段),您可以使用 alias_generator
自动生成别名:
from pydantic import BaseModel
def to_camel(string: str) -> str:
return ''.join(word.capitalize() for word in string.split('_'))
class Voice(BaseModel):
name: str
language_code: str
class Config:
alias_generator = to_camel
voice = Voice(Name='Filiz', LanguageCode='tr-TR')
print(voice.language_code)
#> tr-TR
print(voice.dict(by_alias=True))
#> {'Name': 'Filiz', 'LanguageCode': 'tr-TR'}
(这个脚本是完整的,它应该“按原样”运行)
这里的驼峰案例指的是 “大驼峰案例” 又名帕斯卡案例,例如 驼峰式
。 如果您想改用小驼峰式,例如 camelCase
,而是使用 to_lower_camel
函数。
别名优先(Alias Precedence)¶
Warning
别名优先级逻辑在 v1.4 中发生了变化,以解决以前版本中的错误和意外行为。 在某些情况下,这可能代表一个重大变化,请参阅 #1178 和下面的优先顺序了解详细信息。
在一个字段的别名可能定义在多个地方的情况下,选择的值确定如下(按优先级降序排列):
- 通过
Field(..., alias=<alias>)
直接在模型上设置 - 在
Config.fields
中定义,直接在模型上 - 在父模型上通过
Field(..., alias=<alias>)
设置 - 在父模型的
Config.fields
中定义 - 由
alias_generator
生成,无论它是在模型上还是在父级上
Note
这意味着在子模型上定义的 alias_generator
不会 优先于在父模型中的字段上定义的别名。
例如:
from pydantic import BaseModel, Field
class Voice(BaseModel):
name: str = Field(None, alias='ActorName')
language_code: str = None
mood: str = None
class Character(Voice):
act: int = 1
class Config:
fields = {'language_code': 'lang'}
@classmethod
def alias_generator(cls, string: str) -> str:
# this is the same as `alias_generator = to_camel` above
return ''.join(word.capitalize() for word in string.split('_'))
print(Character.schema(by_alias=True))
"""
{
'title': 'Character',
'type': 'object',
'properties': {
'ActorName': {'title': 'Actorname', 'type': 'string'},
'lang': {'title': 'Lang', 'type': 'string'},
'Mood': {'title': 'Mood', 'type': 'string'},
'Act': {'title': 'Act', 'default': 1, 'type': 'integer'},
},
}
"""
(这个脚本是完整的,它应该“按原样”运行)
智能联合(Smart Union)¶
默认情况下,如 此处 所述,pydantic 尝试按照 Union
的顺序验证(并强制执行)。 所以有时候你可能会有意想不到的强制数据。
from typing import Union
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: Union[str, int]
y: Union[Foo, Bar]
print(Model(x=1, y=Bar()))
#> x='1' y=Foo()
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: str | int
y: Foo | Bar
print(Model(x=1, y=Bar()))
#> x='1' y=Foo()
(这个脚本是完整的,它应该“按原样”运行)
为防止这种情况,您可以启用 Config.smart_union
。 Pydantic 然后会在尝试强制之前检查所有允许的类型。 要知道这当然会更慢,尤其是当你的 Union
很大的时候。
from typing import Union
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: Union[str, int]
y: Union[Foo, Bar]
class Config:
smart_union = True
print(Model(x=1, y=Bar()))
#> x=1 y=Bar()
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: str | int
y: Foo | Bar
class Config:
smart_union = True
print(Model(x=1, y=Bar()))
#> x=1 y=Bar()
(这个脚本是完整的,它应该“按原样”运行)
Warning
请注意,此选项尚不支持复合类型(例如,区分 List[int]
和 List[str]
)。
一旦在 pydantic 中添加严格模式,此选项将得到进一步改进,并且可能成为 v2 中的默认行为!
from typing import List, Union
from pydantic import BaseModel
class Model(BaseModel, smart_union=True):
x: Union[List[str], List[int]]
# Expected coercion
print(Model(x=[1, '2']))
#> x=['1', '2']
# Unexpected coercion
print(Model(x=[1, 2]))
#> x=['1', '2']
from typing import Union
from pydantic import BaseModel
class Model(BaseModel, smart_union=True):
x: Union[list[str], list[int]]
# Expected coercion
print(Model(x=[1, '2']))
#> x=['1', '2']
# Unexpected coercion
print(Model(x=[1, 2]))
#> x=['1', '2']
from pydantic import BaseModel
class Model(BaseModel, smart_union=True):
x: list[str] | list[int]
# Expected coercion
print(Model(x=[1, '2']))
#> x=['1', '2']
# Unexpected coercion
print(Model(x=[1, 2]))
#> x=['1', '2']
(这个脚本是完整的,它应该“按原样”运行)