pydantic basemodel "field" 仅用于验证目的

pydantic basemodel "field" for validation purposes only

考虑以下说明如何使用 pydantic BaseModel 进行验证的代码:

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        return v

user_dict = {'user_id': 10, 'id_key': 60}
u = User(**user_dict)

现在,在我的应用程序中,我真的不希望 id_key 成为像 u 这样的模型实例中的常规、可访问字段——它的唯一目的是验证 user_id.对于我的示例,是否有一种方法可以访问 id_key 以进行验证但又不能将其设为标准字段?

你在 id_check 函数中的 values 参数是属性的内部字典 已经为你的实例验证,如果你需要 id_key 仅在实例化时进行检查而不是之后,您可以简单地将其从 values.

中删除
from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        values.pop('id_key')
        return v
user_dict = {'user_id': 10, 'id_key': 60}
u = User(**user_dict)
print(u)
# output:
# user_id=10

我想为您的代码建议一项额外的改进:在目前的状态下,如果您传递对 [=17 完全无效的内容,pydantic 在返回验证错误之前运行所有字段的验证=] 例如“abc”,或省略它,它不会被添加到 values,并且 user_id 的验证将与 KeyError: 'id_key' 一起崩溃,吞下所有其余的验证过程并没有返回任何合理的消息。

user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# KeyError: 'id_key'

这不是很明确,如果您期望一个 pydantic ValidationError,可能会导致您的应用程序出现问题。您可能需要检查 id_key 是否确实存在于 values 中,如果不存在则直接引发错误。

from pydantic import BaseModel, validator

class User(BaseModel, frozen=True):
    id_key: int
    user_id: int

    @validator('user_id')
    def id_check(cls, v, values):
        if 'id_key' not in values or v > 2 * values['id_key'] + 1:
            raise ValueError('id check failed.')
        values.pop('id_key')
        return v
user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# pydantic.error_wrappers.ValidationError: 2 validation errors for User
# id_key
#   value is not a valid integer (type=type_error.integer)
# user_id
#   id check failed.(type=value_error)