考虑下面的代码,说明使用验证的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
有一个额外的改进,我想建议你的代码:在目前的状态下,pydantic运行所有字段的验证之前返回验证错误,如果你传递一些完全无效的id_key
,如"abc"例如,或者省略它,它将不会被添加到values
,并且user_id
的验证将与KeyError: 'id_key'
一起崩溃,吞噬所有其余的验证过程并且不返回任何有意义的消息。
user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# KeyError: 'id_key'
这不是很明确,如果您期望pydanticValidationError
,可能会导致应用程序出现问题。您可能需要检查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)