21 自定义验证逻辑

在上一篇中,我们探讨了如何使用 Pydantic 进行数据验证与序列化。Pydantic 提供了强大的数据模型创建和验证功能,但在某些情况下,我们可能需要实现更复杂的验证逻辑。在这一节中,我们将介绍如何在 Pydantic 中定义自定义验证器,以实现符合我们业务逻辑的数据验证。

自定义验证器简介

Pydantic 中,我们可以通过定义自定义验证器来扩展基本的验证功能。这些验证器可以是类方法,也可以是实例方法,通常使用 @validator 装饰器来实现。

示例:基本自定义验证器

让我们首先来看一个简单的例子。假设我们有一个模型,要求用户提供一个年龄字段,年龄必须在 0 到 120 之间。我们可以通过自定义验证器来实现这一要求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pydantic import BaseModel, validator, ValidationError

class User(BaseModel):
name: str
age: int

@validator('age')
def validate_age(cls, v):
if not (0 <= v <= 120):
raise ValueError('Age must be between 0 and 120')
return v

# 测试自定义验证器
try:
user = User(name='Alice', age=25)
print(user)

user_invalid = User(name='Bob', age=130) # 触发验证错误
except ValidationError as e:
print(e)

在这个例子中,我们定义了一个 User 模型,并添加了一个名为 validate_age 的自定义验证器。该验证器接收字段值 v 作为参数,如果值不在有效范围内,则抛出 ValueError,这样 Pydantic 将会捕获这个错误并返回相应的验证错误信息。

多个字段之间的验证

有时候,我们需要验证多个字段之间的相互关系。例如,我们想要验证用户的出生年份是否合理,可以根据用户的年龄计算出一个出生年份,并进行检查。我们可以使用 @root_validator 对整个模型进行验证。

示例:多个字段验证

以下是一个关于验证出生年月是否合逻辑的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pydantic import BaseModel, validator, root_validator, ValidationError
from datetime import datetime

class User(BaseModel):
name: str
birth_year: int
age: int

@root_validator
def check_age_and_birth_year(cls, values):
birth_year = values.get('birth_year')
age = values.get('age')

current_year = datetime.now().year
expected_birth_year = current_year - age

if birth_year != expected_birth_year:
raise ValueError('The birth year and age do not match.')

return values

# 测试多个字段验证
try:
user = User(name='Alice', birth_year=1998, age=25) # 合法
print(user)

user_invalid = User(name='Bob', birth_year=1990, age=25) # 触发验证错误
except ValidationError as e:
print(e)

在这个例子中,我们使用 @root_validator 来检查 birth_yearage 这两个字段之间的关系。我们首先计算出根据年龄推算出的出生年份,然后与提供的 birth_year 字段进行对比。

处理复杂的数据结构

在处理复杂的数据结构时,可能需要对嵌套的模型进行自定义验证。Pydantic 支持嵌套模型,我们可以在父模型中对子模型的字段进行验证。

示例:嵌套模型验证

让我们看一个关于订单的例子,我们有一个 Order 模型,其中包含一个 User 模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pydantic import BaseModel, validator, ValidationError

class User(BaseModel):
name: str
age: int

class Order(BaseModel):
user: User
total: float

@validator('total')
def validate_total(cls, v, values):
if v < 0:
raise ValueError('Total must be a positive value.')
if values.get('user').age < 18 and v > 1000:
raise ValueError('Users under 18 cannot make orders over 1000.')
return v

# 测试嵌套模型验证
try:
order = Order(user=User(name='Alice', age=19), total=500)
print(order)

order_invalid = Order(user=User(name='Bob', age=17), total=1500) # 触发验证错误
except ValidationError as e:
print(e)

在这个例子中,我们在 Order 模型中验证了订单的 total 字段,同时考虑了用户的年龄。若用户年龄小于 18 岁,则其订单总额不能超过 1000。

总结

自定义验证器在 Pydantic 中是一个非常强大的功能,允许我们定义复杂的验证逻辑以满足具体的业务需求。在本节中,我们探讨了如何使用 @validator@root_validator 实现单字段和多字段的验证,此外还讨论了如何对嵌套模型进行验证。

在下一篇中,我们将讨论错误处理的常见策略,以及如何优雅地处理和返回验证错误。这样一来,我们就能够为用户提供更好的反馈体验。希望大家在实际开发中能够灵活运用 Pydantic 的验证特性,编写出质量更高的代码!

作者

IT教程网(郭震)

发布于

2024-08-17

更新于

2024-08-18

许可协议

分享转发

交流

更多教程加公众号

更多教程加公众号

加入星球获取PDF

加入星球获取PDF

打卡评论