第 3 章 字段类型与可空值
前两章的文章模型只有标题、内容和阅读量。再往里加,发布状态可以用布尔值,标签是一组字符串,补充信息可以是一份字典。那暂时没有简介时怎么表示?这一章把这些字段加进模型,看看 Pydantic 怎样读取和校验它们。
这里先讲字段类型。长度限制、数值范围、默认值和自定义校验留到后续章节。
本章学习目标
先把常见字段写准确:文字、整数和布尔值分别用 str、int、bool;字符串列表用 list[str],简单字典用 dict[str, str]。你还会用 str | None 表示可空值,并从报错里看出输入与字段类型哪里没对上。
字段类型与模型结构
文章模型会逐步扩展成这样:
title -> str
content -> str
views -> int
is_published -> bool
tags -> list[str]
extra_info -> dict[str, str]
summary -> str | None图里列的是文章模型的字段。接下来从基础类型开始,逐步把列表、字典和可空字段加进来。
每个完整代码块都可以复制到本地 .code/main.py。切换示例时覆盖这个文件,然后在 .code 目录运行 uv run python main.py。
基础字段类型
模型字段写成 字段名: 类型。例如 views: int 表示阅读量是整数,is_published: bool 表示发布状态是布尔值。
类型注解会参与输入校验。"views": "100" 可以转换成整数 100;如果输入 "很多",Pydantic 无法转换,就会报错。布尔值则适合表示是否发布、是否启用这类状态。
先给文章模型增加发布状态:
from pydantic import BaseModel
class ArticleCreate(BaseModel):
title: str
content: str
views: int
is_published: bool
data = {
"title": "Pydantic 字段类型入门",
"content": "这是一篇介绍字段类型的文章",
"views": "100",
"is_published": True,
}
article = ArticleCreate.model_validate(data)
print(article.views)
print(type(article.views))
print(article.is_published)
print(type(article.is_published))运行:
uv run python main.py可能看到类似输出:
100
<class 'int'>
True
<class 'bool'>从输出可以看到,"100" 已经变成整数,is_published 则是布尔值。校验通过后,字段仍按对应的 Python 类型使用。
列表与字典字段
文章通常有多个标签,所以 tags 可以写成 list[str];补充信息是一组键值对,可以写成 dict[str, str]。前者要求列表元素是字符串,后者要求字典的键和值都是字符串。
把这两个字段加入模型:
from pydantic import BaseModel
class ArticleCreate(BaseModel):
title: str
content: str
views: int
is_published: bool
tags: list[str]
extra_info: dict[str, str]
data = {
"title": "Pydantic 字段类型入门",
"content": "这是一篇介绍字段类型的文章",
"views": 100,
"is_published": True,
"tags": ["Python", "Pydantic", "数据校验"],
"extra_info": {
"source": "课程案例",
"level": "入门",
},
}
article = ArticleCreate.model_validate(data)
print(article.tags)
print(article.tags[0])
print(article.extra_info)
print(article.extra_info["source"])运行:
uv run python main.py可能看到类似输出:
['Python', 'Pydantic', '数据校验']
Python
{'source': '课程案例', 'level': '入门'}
课程案例article.tags 还是列表,可以取出第一个标签;article.extra_info 还是字典,可以通过键取到来源。这里先用简单字典,嵌套模型留到后面再讲。
可空字段与类型错误
文章简介有时还没写,可以用 summary: str | None 表示它的值可以是字符串或 None。不过,这里没有设置默认值,所以 summary 仍然是必需字段:提交数据时要提供它,只是值可以是 None。字段默认值会在下一章介绍。
下面的脚本先校验 summary 分别为 None 和字符串的两份数据,再试一次错误输入:模型要求 tags 是字符串列表,输入却给了一个字符串。
from pydantic import BaseModel, ValidationError
class ArticleCreate(BaseModel):
title: str
content: str
views: int
is_published: bool
tags: list[str]
extra_info: dict[str, str]
summary: str | None
data = {
"title": "Pydantic 字段类型入门",
"content": "这是一篇介绍字段类型的文章",
"views": 100,
"is_published": True,
"tags": ["Python", "Pydantic"],
"extra_info": {
"source": "课程案例",
"level": "入门",
},
"summary": None,
}
article = ArticleCreate.model_validate(data)
print(article.summary)
print(type(article.summary))
text_data = {**data, "summary": "这是一篇字段类型介绍"}
text_article = ArticleCreate.model_validate(text_data)
print(text_article.summary)
print(type(text_article.summary))
bad_data = {
"title": "Pydantic 字段类型入门",
"content": "这是一篇介绍字段类型的文章",
"views": 100,
"is_published": True,
"tags": "Python",
"extra_info": {
"source": "课程案例",
"level": "入门",
},
"summary": None,
}
try:
bad_article = ArticleCreate.model_validate(bad_data)
print(bad_article)
except ValidationError as e:
print("数据校验失败")
print(e)运行:
uv run python main.py错误输出可能还包含输入值和错误类型;先看字段名和核心原因:
None
<class 'NoneType'>
这是一篇字段类型介绍
<class 'str'>
数据校验失败
1 validation error for ArticleCreate
tags
Input should be a valid list前四行显示 summary 可以接收 None 或字符串。错误指向 tags:模型要求列表,输入却是字符串。
这几种类型可以放在一起查:
| 类型 | 写法 | 适合表示 |
|---|---|---|
| 字符串 | title: str | 标题、内容、分类 |
| 整数 | views: int | 阅读量、点赞数 |
| 布尔值 | is_published: bool | 是否发布、是否置顶 |
| 字符串列表 | tags: list[str] | 标签、关键词 |
| 字符串字典 | extra_info: dict[str, str] | 简单补充信息 |
| 可空字符串 | summary: str | None | 简介、备注 |
综合校验
现在把这些字段放进同一份文章数据里。正确输入会生成模型对象;错误输入的 tags 虽然是列表,但第二个元素是整数,不符合 list[str]。
from pydantic import BaseModel, ValidationError
class ArticleCreate(BaseModel):
title: str
content: str
views: int
is_published: bool
tags: list[str]
extra_info: dict[str, str]
summary: str | None
data = {
"title": "Pydantic 字段类型入门",
"content": "这是一篇介绍字段类型的文章",
"views": "100",
"is_published": True,
"tags": ["Python", "Pydantic", "数据校验"],
"extra_info": {
"source": "课程案例",
"level": "入门",
},
"summary": None,
}
article = ArticleCreate.model_validate(data)
print("文章标题:", article.title)
print("阅读量:", article.views)
print("是否发布:", article.is_published)
print("文章标签:", article.tags)
print("来源:", article.extra_info["source"])
print("文章简介:", article.summary)
bad_data = {
"title": "Pydantic 字段类型入门",
"content": "这是一篇介绍字段类型的文章",
"views": 100,
"is_published": True,
"tags": ["Python", 123, "数据校验"],
"extra_info": {
"source": "课程案例",
"level": "入门",
},
"summary": None,
}
try:
bad_article = ArticleCreate.model_validate(bad_data)
print(bad_article)
except ValidationError as e:
print("错误数据校验失败")
print(e)运行:
uv run python main.py可能看到类似输出:
文章标题: Pydantic 字段类型入门
阅读量: 100
是否发布: True
文章标签: ['Python', 'Pydantic', '数据校验']
来源: 课程案例
文章简介: None
错误数据校验失败
1 validation error for ArticleCreate
tags.1
Input should be a valid string前半段是校验成功后的字段值。错误里的 tags.1 指向列表索引 1,也就是第二个元素;这里传入的是整数,不是字符串。
前一张图展示模型有哪些字段,这张图展示输入怎样经过校验。字段类型既描述数据结构,也决定 Pydantic 如何转换和检查输入。
本章小结
字段类型写清楚,Pydantic 才知道该怎样处理输入。str | None 允许值为 None,却不代表这个字段可以不传;没有默认值时,它仍是必需字段。输入类型不匹配、又无法转换,就会收到 ValidationError。