pydantic之Field使用教程
下面提供一个针对 Pydantic 中 Field 的通俗易懂、又较为全面的中文教程,适合初学者(“小白”)理解和上手。内容包括 Field 的作用、常用参数、在模型验证和文档生成中的意义,以及丰富的示例与注意事项。
一、什么是 Pydantic 和 Field
- Pydantic 是一个用于数据校验和设置的 Python 库,常用于 FastAPI、数据处理脚本等场景。它通过 Python 类型注解(type hints)来定义数据模型,并在实例化时自动校验和转换输入数据。
Field是 Pydantic 提供的一个函数/标记,用于在模型属性(字段)上指定更丰富的元信息和校验约束。例如:默认值、校验范围、描述文档、示例、别名等。
简单来说,Field 就像给模型字段“贴标签”,告诉 Pydantic 该字段应如何校验、如何在 OpenAPI 文档中展示、默认值是多少等。
二、Field 的基本用法
2.1 导入与基本语法
from pydantic import BaseModel, Field
class User(BaseModel):
username: str = Field(...) # “...” 表示必须提供该字段
age: int = Field(default=0) # 如果不提供,默认为 0
-
Field(...)中通常第一个参数是 default 或 default_factory:Field(default_value):若用户未提供该字段,则使用default_value。Field(...):...表示“这个字段必填”(no default),如果创建模型时未提供会报错。Field(default_factory=callable):通过可调用对象生成默认值,如Field(default_factory=list)表示默认[],每次新实例化时调用一次函数以免所有实例共用同一个可变默认。
2.2 最简单示例
class Item(BaseModel):
name: str = Field(..., title="名称", description="项目名称,必填")
price: float = Field(0.0, gt=0, description="价格,必须大于0")
name:使用Field(..., title="名称", description="项目名称,必填")强调必填,并添加标题和描述,方便自动生成文档。price:默认值为0.0,同时用gt=0约束大于 0;若输入为负数或 0,会报校验错误。
三、Field 常用参数详解
以下列出 Field(...) 中常见的参数及其作用,便于理解和记忆。格式:Field(default, 参数名=值, ...)。
-
default / default_factory
default:字段默认值,如Field(5)、Field("abc")、Field(None)。default_factory:可调用,用于生成默认值,如Field(default_factory=list)、Field(default_factory=lambda: datetime.utcnow())。- 注意:default 和 default_factory 不能同时使用。
-
校验约束(numeric、string、序列等)
-
数值类型:
gt、ge、lt、legt: “greater than”,严格大于;ge: “greater or equal”,大于等于;同理lt,le。- 示例:
age: int = Field(..., ge=0, lt=150)表示年龄在 [0,150) 之间。
-
字符串长度:
min_length、max_length- 仅对字符串类型有效:
name: str = Field(..., min_length=1, max_length=50)。
- 仅对字符串类型有效:
-
正则表达式:
regexphone: str = Field(..., regex=r"^\d{10,11}$"),确保字符串满足正则。
-
列表/集合类型长度:
min_items、max_items- 对序列类型生效:
tags: List[str] = Field(default_factory=list, min_items=1, max_items=5)。
- 对序列类型生效:
-
数组元素校验:可配合 Pydantic 泛型和子模型使用,Field 本身不对元素类型做深度校验,但 Pydantic 会结合类型注解校验每个元素类型。
-
-
文档和元信息
-
title:字段标题,在自动生成文档(如 OpenAPI/Swagger)中显示为该字段的标题。 -
description:字段描述,自动文档中显示详细说明。 -
example或examples:在 Pydantic V1 中,schema_extra用于示例;在 FastAPI 自动文档中,可在路由中定义example。Field 也支持example(Pydantic V2 支持),或通过 schema_extra 全局添加。 -
alias:字段别名,表示 JSON 输入/输出时使用的键名。例如:class User(BaseModel): full_name: str = Field(..., alias="fullName")- 创建时可用
{ "fullName": "张三" },但访问属性时为user.full_name。 - 设置
Config中allow_population_by_field_name = True可以同时支持通过属性名赋值。
- 创建时可用
-
const(仅 Pydantic V2):表示字段值必须恒定(与 default 一致),类似常量。 -
deprecated: 标记字段已过时(在自动文档里提示废弃)。 -
multiple_of: 对数值类型,要求可被某个数整除。 -
strict: 是否开启严格模式(例如类型强转限制更严),Pydantic V1 / V2 具体差异需参考对应版本文档。
-
-
校验顺序细节
- Pydantic 会先按照类型注解对传入值做类型转换(如
"123"转为 int 123),然后再检查 Field 中的约束(如ge、regex等)。如果类型转换失败或约束检查失败,就抛出 ValidationError。 - 对可选类型(
Optional[...]或Union[..., None])允许None,但若 Field 加了min_length等检查,在值为None时会跳过对应检查或报错,视具体情况而定。建议 Optional 字段不要加不适用的约束。
- Pydantic 会先按照类型注解对传入值做类型转换(如
-
示例:多个约束组合
from typing import List, Optional
from pydantic import BaseModel, Field
class Product(BaseModel):
id: int = Field(..., gt=0, description="商品 ID,必须正整数")
name: str = Field(..., min_length=1, max_length=100, description="商品名称,1-100 字符")
price: float = Field(..., ge=0.0, description="价格,不可为负")
tags: List[str] = Field(default_factory=list, min_items=0, max_items=10, description="标签列表,最多 10 项")
description: Optional[str] = Field(None, max_length=500, description="商品描述,最多 500 字")
四、用于 FastAPI 自动文档
在 FastAPI 中使用 Pydantic 模型作为请求体或响应模型时,Field 提供的 title、description、example、alias 等元信息会自动体现在 Swagger UI 或 Redoc 中,让前后端协作更流畅。
示例:
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str = Field(..., title="名称", description="商品名称", example="苹果")
price: float = Field(..., gt=0, description="价格,必须大于 0", example=9.9)
@app.post("/items", response_model=Item)
def create_item(item: Item):
# item.name, item.price 都已校验通过
return item
- 在 Swagger UI 的请求体示例中,会显示字段名称、示例值、描述等,帮助前端理解如何调用接口。
- 如果使用
alias,在文档中也会展示别名,注意需在模型 Config 中设置allow_population_by_field_name以兼容。
五、Field 与 Config 结合使用
Pydantic 模型还支持 Config 内部类来配置更多全局行为。常见与 Field 结合的配置:
-
orm_mode = True-
当返回数据库 ORM 对象(如 SQLAlchemy model)时,可直接通过 Pydantic 模型序列化。Field 中的约束仍生效。
-
示例:
class UserOut(BaseModel): id: int username: str class Config: orm_mode = True -
FastAPI 会自动用 Pydantic 将 ORM 返回的对象转换为 dict,再由 ORJSONResponse 等序列化发送。
-
-
allow_population_by_field_name = True-
如果你在 Field 中使用
alias,此配置允许在初始化模型时使用字段名赋值。class User(BaseModel): full_name: str = Field(..., alias="fullName") class Config: allow_population_by_field_name = True user = User(fullName="张三") user2 = User(full_name="李四") # 也可这样 -
在 FastAPI 请求场景中,一般前端传递 JSON 用 alias 即可;若需要在 Python 代码中以属性名创建实例,可启用此选项。
-
-
use_enum_values = True-
如果字段是枚举类型(
Enum),可以让 Pydantic 在序列化时使用枚举的值而非名称。常与 Field 一起使用枚举字段。from enum import Enum class Role(str, Enum): admin = "admin" user = "user" class User(BaseModel): username: str role: Role = Field(default=Role.user, description="角色") class Config: use_enum_values = True
-
-
validate_assignment = True-
允许在模型实例属性赋值时重新校验。若你希望对运行时修改字段做校验,可开启此项。
class Person(BaseModel): age: int = Field(..., ge=0) class Config: validate_assignment = True p = Person(age=10) p.age = -5 # 立即抛 ValidationError
-
-
Pydantic V2 中的更多配置
- 如果使用 Pydantic V2,Field 参数与 Config 选项可能有更新,建议查看官方文档。但大多数概念相通:Field 用于字段级别元信息和校验,Config 用于模型级全局行为。
六、默认值与 default_factory 深度说明
-
default:若字段常量或不依赖运行时数据,用Field("abc")、Field(123)。 -
default_factory:当默认值需要在运行时生成、或是可变对象(列表、字典)时,用default_factory,避免多个实例共用同一可变对象。例如:class Data(BaseModel): items: list[int] = Field(default_factory=list) -
注意:不要把可变默认写在直接赋值上,如
items: list[int] = [],Pydantic 可能会将同一个列表在多个实例间共享,引发意外。改用default_factory=list。 -
使用场景:当默认值需根据当前时间动态生成时,可以:
from datetime import datetime class Event(BaseModel): created_at: datetime = Field(default_factory=datetime.utcnow)
七、高级示例:嵌套模型与 Field
当模型中嵌套其他 Pydantic 模型时,Field 也可为嵌套模型字段提供默认值或元信息:
class Address(BaseModel):
city: str = Field(..., description="城市")
zip_code: str = Field(..., regex=r"^\d{5}$", description="邮政编码5位数字")
class User(BaseModel):
username: str = Field(..., min_length=1)
address: Address = Field(..., description="用户地址信息")
-
如果需要默认嵌套值,可用
default_factory:class User(BaseModel): username: str = Field(...) address: Address = Field(default_factory=lambda: Address(city="未知", zip_code="00000")) -
嵌套校验:Pydantic 会递归校验嵌套模型,每个字段的 Field 约束都会生效。
八、Field 在 Schema/JSON Schema 生成中的作用
-
Pydantic 模型可以生成 JSON Schema,用于文档、前端校验等。Field 中的元信息会映射到 JSON Schema:
title→"title"description→"description"default→"default"example→"example"gt,le等数值约束 →"minimumExclusive","maximumInclusive"等(具体名称依据 JSON Schema 版本)regex→"pattern"
-
FastAPI 利用 Pydantic 的 JSON Schema 生成 OpenAPI 文档,Field 中填的描述和示例都会显示在 Swagger UI 中,帮助前端更好理解接口。
可通过以下方式查看生成的 Schema:
from pydantic import BaseModel, Field
class User(BaseModel):
username: str = Field(..., title="用户名", min_length=1, max_length=32)
age: int = Field(0, ge=0, le=150)
# 查看 JSON Schema
print(User.schema_json(indent=2, ensure_ascii=False))
结果中会看到 "title": "用户名", "minLength": 1, "maximum": 150 等信息。
九、错误与调试
-
ValidationError 信息
-
当实例化模型时,如果输入不符合 Field 约束,Pydantic 会抛出
ValidationError,并给出详细错误位置和类型。例如:try: User(username="", age=-5) except ValidationError as e: print(e.json()) -
错误信息会指出哪个字段、哪种校验失败(如
ensure this value has at least 1 characters、value is not greater than 0等),帮助快速定位问题。
-
-
调试 Field 约束
- 如果某个约束似乎无效,首先确认字段类型注解是否正确,如
age: int才会应用gt,ge;如果是Optional[int],需要注意 None 行为。 - 确认是否在模型 Config 中有影响验证行为的设置(如
validate_assignment,arbitrary_types_allowed等)。 - 对于复杂正则,请在单独环境测试正则再放到 Field 中。
- 如果某个约束似乎无效,首先确认字段类型注解是否正确,如
-
兼容 Pydantic V1 vs V2
- 不同版本 Field 参数可能略有差异,若项目升级 Pydantic,需参考对应版本文档。大多数常用参数(gt, ge, min_length 等)在两版中类似。
十、实战小结
-
为什么要用 Field
- 校验约束:通过 Field 指定范围、长度、正则等,自动校验输入数据,保证数据质量。
- 自动文档:在 FastAPI 等框架中,Field 的
title、description、example会自动体现在 Swagger UI 上,极大提高前后端沟通效率。 - 默认值与动态默认:用 default 和 default_factory 管理默认值,避免可变默认陷阱。
- 别名与序列化定制:通过 alias 控制 JSON 键名,使内部属性和外部接口字段解耦;配合 Config,可双向赋值。
- Schema 生成:Field 元信息会体现在生成的 JSON Schema 中,可用于前端校验、文档生成、客户端生成代码等。
-
如何学习和验证
- 多写小示例,在 REPL 或脚本中实例化模型,观察校验行为;打印
Model.schema_json()查看生成 Schema。 - 在 FastAPI 项目中试用 Field 的各种参数,打开
/docs看效果;结合 Postman/Swagger 测试边界情况。 - 阅读官方文档:Pydantic Field 章节(确认 Pydantic 版本),理解 JSON Schema 映射规则。
- 多写小示例,在 REPL 或脚本中实例化模型,观察校验行为;打印
-
常见注意事项
- 可变默认使用
default_factory;避免把业务逻辑放在 Field,Field 只做数据定义和校验,不适合写额外复杂逻辑。 - 校验与业务分离:Field 负责基础类型和简单约束(范围、长度、格式);更复杂的业务校验(如唯一性检查、跨字段关联校验)可在代码中或 Pydantic 的
@root_validator/自定义验证函数中实现。 - 配合 Config 做更高级用法:如 ORM 模式、别名、严格模式、验证赋值等。
- 可变默认使用
附:一个综合示例
from typing import List, Optional
from datetime import datetime
from enum import Enum
from pydantic import BaseModel, Field, root_validator, ValidationError
class Role(str, Enum):
admin = "admin"
user = "user"
guest = "guest"
class Address(BaseModel):
city: str = Field(..., description="城市名", min_length=1)
zip_code: str = Field(..., regex=r"^\d{5}$", description="5 位邮编")
class UserIn(BaseModel):
username: str = Field(..., min_length=3, max_length=32, description="用户名,3-32 字符")
password: str = Field(..., min_length=6, description="密码,至少6位")
age: Optional[int] = Field(None, ge=0, le=120, description="年龄,可选,0-120")
roles: List[Role] = Field(default_factory=lambda: [Role.user], description="用户角色列表")
address: Optional[Address] = Field(None, description="地址信息")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
bio: Optional[str] = Field(None, max_length=200, description="个人简介,不超过200字符")
@root_validator
def check_age_for_role(cls, values):
age = values.get("age")
roles = values.get("roles", [])
# 假设逻辑:如果未满18岁,不允许 admin 角色
if age is not None and age < 18 and Role.admin in roles:
raise ValueError("未满18岁用户不能拥有 admin 角色")
return values
class Config:
orm_mode = True
allow_population_by_field_name = True
# 测试
try:
u = UserIn(
username="张三",
password="secret123",
age=16,
roles=["user", "admin"], # 触发 root_validator 报错
address={"city": "北京", "zip_code": "10001"}
)
except ValidationError as e:
print("校验错误:", e)
# 查看 schema
print(UserIn.schema_json(indent=2, ensure_ascii=False))
- 通过 Field 指定了多种约束、默认值、描述等;嵌套 Address 模型也带 Field 校验;使用 Enum 角色;root_validator 做跨字段校验;Config 开启 ORM 模式和别名赋值支持;最后生成 JSON Schema 可用于文档或前端校验。
以上即 Pydantic Field 的全面教程,从基本语法到常用参数、FastAPI 文档支持、Config 结合、高级示例、注意事项等,覆盖了初学者需要了解的大部分内容。建议在实际项目中多练习,打开 Swagger 文档观察效果,逐步加深理解。祝你学习顺利!

浙公网安备 33010602011771号