model config

在2.0之前,配置项在model类的class Config中编写,2.0之后,使用model_config=ConfigDict(**kwagrs)。

全局修改配置

创建自己的Model父类,所有model继承该类。
关于ConfigDict的参数见文档或者源码

from pydantic import BaseModel, ConfigDict


class Parent(BaseModel):
    model_config = ConfigDict(extra='allow')


class Model(Parent):
    x: str


m = Model(x='foo', y='bar')
print(m.model_dump())
#> {'x': 'foo', 'y': 'bar'}

子类和父类的model_config会合并。

别名生成

Python变量规范蛇形命名法为主,而Java,前端是驼峰命名法,数据库也推荐蛇形命名法。在Java后端中,一般将数据库查出的蛇形字段转换为驼峰命名法,Python使用蛇形命名法,但数据返回前端需要转换成驼峰命名。

from typing import Literal, Any

from pydantic import BaseModel, ConfigDict, Field
from pydantic.alias_generators import to_camel


class Voice(BaseModel):
    def model_dump(
            self,
            *,
            mode: Literal['json', 'python'] | str = 'python',
            include=None,
            exclude=None,
            by_alias: bool = False,
            exclude_unset: bool = False,
            exclude_defaults: bool = False,
            exclude_none: bool = False,
            round_trip: bool = False,
            warnings: bool = True,
    ) -> dict[str, Any]:
        return self.__pydantic_serializer__.to_python(self, mode=mode, include=include, exclude=exclude, by_alias=True,
                                                      exclude_unset=exclude_unset, exclude_defaults=exclude_defaults,
                                                      exclude_none=True, round_trip=round_trip, warnings=warnings)

    model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)

    name: str = Field(alias='username')
    language_code: str = Field(alias='langcode', )


voice = Voice(username='Filiz', langcode='tr-TR')
print(voice.language_code)
# > tr-TR
print(voice.model_dump())
# {'username': 'Filiz', 'langcode': 'tr-TR'}
  • alias_generator指定命名转换方式。
  • 默认情况下,指定alias_generator之后,输入的值也需要驼峰命名为key,populate_by_name=True表示同时支持原本属性名以及驼峰命名。
  • 默认情况下,Field的alias优先级高于alias_generator,如需设置后者的优先级更高,alias_priority=1。
  • 重写model_dump方法,设置alias为true。

在model_config中设置alias_generator为驼峰,populate_by_name为True,Field不设置alias,同时重写model_dump设置by_alias为True,可以满足后台蛇形命名,返回数据驼峰命名的需求。

额外的属性

对传入的多余的属性,有三种处理方法。

  • ignore,忽略。
  • forbid,抛出异常。
  • allow,保留。

修改后再次校验

默认情况下Model只有在创建时会进行数据校验,后续的赋值不会再校验,如需要,设置validate_assignment=True每次修改后校验。

Revalidate instances

对象只有初始化时会执行校验,当作为另一个对象的属性时,不会对其属性再次进行校验,参考以下代码。

from typing import List

from pydantic import BaseModel


class User(BaseModel, revalidate_instances='never'):  
    hobbies: List[str]


class SubUser(User):
    sins: List[str]


class Transaction(BaseModel):
    user: User


my_user = User(hobbies=['reading'])
t = Transaction(user=my_user)
print(t)
#> user=User(hobbies=['reading'])

my_user.hobbies = [1]  
t = Transaction(user=my_user)  
print(t)
#> user=User(hobbies=[1])

my_sub_user = SubUser(hobbies=['scuba diving'], sins=['lying'])
t = Transaction(user=my_sub_user)
print(t)
#> user=SubUser(hobbies=['scuba diving'], sins=['lying'])

user实例化之后修改属性,由于没有设置validate_assignment,不会进行校验,当作为属性传入Transaction后,不会报错。

Revalidate instances的值可以是’never’和’always’。

允许非Model作为属性

arbitrary_types_allowed=True

Q.E.D.


一切很好,不缺烦恼。