Basemodel 属性改名/添加/删除
如果basemodel如何一个字段可以有也可以没有
在 Pydantic BaseModel 里,一个字段“可以有也可以没有”,通常这样写:
from pydantic import BaseModel
from typing import Optional
class User(BaseModel):
name: str
age: Optional[int] = None
这样 age 就是可选字段:
User(name="Tom")
# age=None
User(name="Tom", age=18)
# age=18
如果是 Python 3.10+,也可以写成:
class User(BaseModel):
name: str
age: int | None = None
关键点是:
age: int | None = None
表示:
age可以是int- 也可以是
None - 不传这个字段也可以
注意不要只写:
age: Optional[int]
在一些 Pydantic 版本里,这表示值可以是 None,但字段本身仍然可能是必填的。最稳妥写法是加默认值:
age: Optional[int] = None
那如何同时=Field
可以同时用 Field,把默认值放在 Field 的第一个参数里:
from pydantic import BaseModel, Field
class User(BaseModel):
name: str
age: int | None = Field(default=None, description="用户年龄")
或者更简洁:
class User(BaseModel):
name: str
age: int | None = Field(None, description="用户年龄")
这样 age 就是:可以不传、可以传 None、也可以传 int。
User(name="Tom")
User(name="Tom", age=None)
User(name="Tom", age=18)
如果你想“字段可以不传,但一旦传了就不能是 None”,则写成:
class User(BaseModel):
name: str
age: int = Field(default=None, description="用户年龄")
不过这个写法在类型语义上不太严谨,因为默认值是 None,类型却是 int。更推荐前面的:
age: int | None = Field(default=None, description="用户年龄")
User声明的对象如何添加属性
如果是 Pydantic BaseModel 的对象,比如:
from pydantic import BaseModel
class User(BaseModel):
name: str
user = User(name="Tom")
默认情况下,能不能“临时添加新属性”取决于 Pydantic 版本和配置。
推荐方式:在模型里先声明字段
class User(BaseModel):
name: str
age: int | None = None
user = User(name="Tom")
user.age = 18
这是最推荐的方式。
允许动态添加额外属性
Pydantic v2:
from pydantic import BaseModel, ConfigDict
class User(BaseModel):
model_config = ConfigDict(extra="allow")
name: str
user = User(name="Tom")
user.age = 18
print(user.age)
Pydantic v1:
from pydantic import BaseModel
class User(BaseModel):
name: str
class Config:
extra = "allow"
user = User(name="Tom")
user.age = 18
print(user.age)
不修改原对象,生成一个带新值的新对象
如果属性已经在模型里声明过,可以用:
Pydantic v2:
new_user = user.model_copy(update={"age": 18})
Pydantic v1:
new_user = user.copy(update={"age": 18})
总结一下:如果这个属性是业务字段,最好在 User 里声明;如果确实需要运行时动态加字段,就配置 extra="allow"。
如何删除属性
在 Pydantic BaseModel 对象里删除属性,分几种情况。
1. 普通 Python 方式:delattr
如果模型允许额外字段,或者字段本身存在:
delattr(user, "age")
等价于:
del user.age
例如:
from pydantic import BaseModel, ConfigDict
class User(BaseModel):
model_config = ConfigDict(extra="allow")
name: str
user = User(name="Tom")
user.age = 18
del user.age
2. 更安全:先判断有没有
if hasattr(user, "age"):
delattr(user, "age")
3. 如果是模型声明字段,不建议真的删除
例如:
class User(BaseModel):
name: str
age: int | None = None
虽然可以尝试:
del user.age
但删除后这个对象可能变得“不完整”,后面访问可能报错:
print(user.age) # 可能 AttributeError
更推荐把它设为 None:
user.age = None
4. 不修改原对象,生成一个“去掉字段”的 dict
很多时候你不是要真的删除属性,而是导出时不包含它:
Pydantic v2:
data = user.model_dump(exclude={"age"})
Pydantic v1:
data = user.dict(exclude={"age"})
5. 删除动态额外字段
Pydantic v2 里,如果是 extra="allow" 添加的额外字段,也可以这样:
if "age" in user.model_extra:
del user.model_extra["age"]
不过一般直接用:
delattr(user, "age")
就够了。
basemodel如何挑选特定字段转换为json,这些字段可能存在嵌套结构
在 Pydantic 里,推荐用 include 来“挑选特定字段”,再转 JSON。嵌套结构也可以用字典形式指定。
Pydantic v2
json_str = user.model_dump_json(
include={
"name": True,
"profile": {
"email": True,
"address": {
"city": True
}
}
}
)
例如:
from pydantic import BaseModel
class Address(BaseModel):
city: str
country: str
class Profile(BaseModel):
email: str
phone: str
address: Address
class User(BaseModel):
id: int
name: str
password: str
profile: Profile
user = User(
id=1,
name="Tom",
password="secret",
profile={
"email": "tom@example.com",
"phone": "123456",
"address": {
"city": "Shanghai",
"country": "China"
}
}
)
json_str = user.model_dump_json(
include={
"id": True,
"name": True,
"profile": {
"email": True,
"address": {
"city": True
}
}
}
)
print(json_str)
输出类似:
{"id":1,"name":"Tom","profile":{"email":"tom@example.com","address":{"city":"Shanghai"}}}
Pydantic v1
json_str = user.json(
include={
"id": True,
"name": True,
"profile": {
"email": True,
"address": {
"city": True
}
}
}
)
嵌套列表里的字段
如果字段是列表,例如:
class Order(BaseModel):
id: int
price: float
secret: str
class User(BaseModel):
name: str
orders: list[Order]
只保留每个订单的 id 和 price:
json_str = user.model_dump_json(
include={
"name": True,
"orders": {
"__all__": {
"id": True,
"price": True
}
}
}
)
Pydantic v1 也是类似:
json_str = user.json(
include={
"name": True,
"orders": {
"__all__": {
"id": True,
"price": True
}
}
}
)
如果只是想得到 dict
Pydantic v2:
data = user.model_dump(include={...})
Pydantic v1:
data = user.dict(include={...})
核心写法就是:
include = {
"字段1": True,
"嵌套字段": {
"子字段": True
},
"列表字段": {
"__all__": {
"子字段": True
}
}
}

浙公网安备 33010602011771号