Skip to content

第 2 章 BaseModel 与模型对象 ​

上一章已经用 BaseModel 校验过文章数据。这次我们把几个容易混在一起的名字分清楚:ArticleCreate 是模型类,article 是什么?它和原始字典 data 又有什么区别?

本章学习目标 ​

这章要把模型真正用起来:自己定义一个基础模型,分清模型类、模型对象和普通字典,并知道字段名、类型注解各管什么。随后用 model_validate() 校验字典;遇到常见错误时,也能判断问题出在哪一步。

从模型类到模型对象 ​

继续使用文章数据:

python
data = {
    "title": "Pydantic 入门",
    "content": "这是一篇文章",
    "views": 100,
}

字典里有一篇具体文章,但它没有说明文章创建数据需要哪些字段、各字段是什么类型。我们先把结构写进模型,再把这份数据交给它。

每个完整代码块都可以复制到本地 .code/main.py。切换示例时覆盖这个文件,然后在 .code 目录运行 uv run python main.py。

模型类描述数据结构 ​

BaseModel 是 Pydantic 提供的基础类。继承它以后,模型才能根据字段声明校验输入、进行基础类型转换,并在成功时生成模型对象。

字段写成 字段名: 类型:左边是字段名,右边是类型要求。比如 title: str 表示标题是字符串,views: int 表示阅读量是整数。类型注解也会参与 Pydantic 的输入校验。

先只定义模型,暂时不传入数据:

py
from pydantic import BaseModel


class ArticleCreate(BaseModel):
    title: str
    content: str
    views: int

运行:

bash
uv run python main.py

程序正常结束,没有输出。这是预期结果:ArticleCreate 现在只描述文章数据的结构,还没有对应某一篇具体文章。

从字典生成模型对象 ​

data 仍是普通字典。调用 ArticleCreate.model_validate(data) 后,Pydantic 会检查必需字段是否齐全、输入值是否符合类型要求;校验通过才会返回模型对象 article。

text
ArticleCreate -> 模型类,描述数据结构
data          -> 普通字典,保存原始输入
article       -> 模型对象,保存校验后的数据

把字典交给模型:

py
from pydantic import BaseModel


class ArticleCreate(BaseModel):
    title: str
    content: str
    views: int


data = {
    "title": "Pydantic 入门",
    "content": "这是一篇文章",
    "views": 100,
}

article = ArticleCreate.model_validate(data)

print(article)
print(article.title)
print(article.content)
print(article.views)

运行:

bash
uv run python main.py

可能看到类似输出:

text
title='Pydantic 入门' content='这是一篇文章' views=100
Pydantic 入门
这是一篇文章
100

默认情况下,模型未声明的额外字段会被忽略。必需字段名如果写错,比如输入只有 view,views 仍然缺失,校验会失败。

模型对象与普通字典 ​

现在用同一份文章数据分别通过字典和模型对象取标题:

py
from pydantic import BaseModel


class ArticleCreate(BaseModel):
    title: str
    content: str
    views: int


data = {
    "title": "Pydantic 入门",
    "content": "这是一篇文章",
    "views": 100,
}

article = ArticleCreate.model_validate(data)

print("字典访问标题:", data["title"])
print("模型对象访问标题:", article.title)

print("字典本身:", data)
print("模型对象:", article)

运行:

bash
uv run python main.py

可能看到类似输出:

text
字典访问标题: Pydantic 入门
模型对象访问标题: Pydantic 入门
字典本身: {'title': 'Pydantic 入门', 'content': '这是一篇文章', 'views': 100}
模型对象: title='Pydantic 入门' content='这是一篇文章' views=100

字典用 data["title"] 取值,模型对象用 article.title 取值。model_validate() 返回新的模型对象,data 本身还是字典;后续代码可以使用通过校验的 article。

模型类、模型对象与普通字典的关系

输入校验错误 ​

模型要求 views: int,输入却是无法转换为整数的 "abc"。这种情况下,model_validate() 会抛出 ValidationError,不会返回模型对象。下面的代码捕获错误,让程序继续运行:

py
from pydantic import BaseModel, ValidationError


class ArticleCreate(BaseModel):
    title: str
    content: str
    views: int


bad_data = {
    "title": "Pydantic 入门",
    "content": "这是一篇文章",
    "views": "abc",
}

try:
    article = ArticleCreate.model_validate(bad_data)
    print(article)
except ValidationError as e:
    print("数据校验失败")
    print(e)

运行:

bash
uv run python main.py

错误信息可能还会列出输入值和错误类型;这里先看字段名和核心原因:

text
数据校验失败
1 validation error for ArticleCreate
views
  Input should be a valid integer

模型要求整数,"abc" 无法转换。程序进入 except ValidationError 后,就不会继续使用这份错误数据。

常见模型使用错误 ​

常见错误的三个阶段

这几种问题分别发生在模型定义、输入校验和对象访问时。出错时先看代码停在哪一步。

忘记继承 BaseModel:

python
class ArticleCreate:
    title: str
    content: str
    views: int

这是普通类,不是 Pydantic 模型。调用 ArticleCreate.model_validate(data) 时会发现类上没有这个方法。

字段没有类型注解:

python
class ArticleCreate(BaseModel):
    title = "Pydantic 入门"
    content = "这是一篇文章"
    views = 100

模型字段要写成 字段名: 类型。上面的写法会在定义类时触发 PydanticUserError,还没有进入输入校验。

必需字段名写错:模型要求 views: int,输入却写成 view:

python
"view": 100

默认配置会忽略未知字段 view,同时发现必需字段 views 缺失,因此校验失败。

访问不存在的字段:

python
print(article.author)

如果模型里没有 author,访问 article.author 会触发 AttributeError。这不是输入校验错误,而是访问了模型中不存在的属性。

完整校验流程 ​

最后让正确输入和错误输入走一遍完整流程:先校验并访问模型对象,再捕获不符合要求的数据。

py
from pydantic import BaseModel, ValidationError


class ArticleCreate(BaseModel):
    title: str
    content: str
    views: int


data = {
    "title": "Pydantic 入门",
    "content": "这是一篇文章",
    "views": 100,
}

article = ArticleCreate.model_validate(data)

print("=== 校验成功后的模型对象 ===")
print(article)
print("文章标题:", article.title)
print("文章内容:", article.content)
print("阅读量:", article.views)

bad_data = {
    "title": "Pydantic 入门",
    "content": "这是一篇文章",
    "views": "abc",
}

try:
    bad_article = ArticleCreate.model_validate(bad_data)
    print(bad_article)
except ValidationError as e:
    print("=== 错误数据校验失败 ===")
    print(e)

运行:

bash
uv run python main.py

运行后先看到正确文章的标题、内容和阅读量,随后看到错误数据在 views 字段上的校验失败:

text
定义模型类
    ↓
准备普通字典
    ↓
调用 model_validate()
    ├─ 成功:得到模型对象,通过属性访问字段
    └─ 失败:捕获 ValidationError,处理错误输入

本章小结 ​

ArticleCreate 定义结构,data 是原始字典;model_validate() 校验通过,才会得到 article 这个模型对象。字段少了类型注解、输入没通过校验、访问了不存在的属性,看起来都像“报错”,却发生在不同阶段。排查时先分清阶段。