Consider the follwoing code illustrating use of the pydantic
BaseModel
with validation:
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)
Now, in my application, I don't really want id_key
to be a regular, accessible field in model instances like u
--its sole purpose is for validating user_id
. For my example, is there a way to have access to id_key
for validation purposes but not have it be a standard field?
CodePudding user response:
The values
argument you have in your id_check
function being the internal dict of attributes already validated for your instance, if you need to have id_key
only at instantiation time for checking and not after that, you could simply remove it from 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
There is one additional improvement I'd like to suggest for your code: in its present state, as pydantic runs the validations of all the fields before returning the validation errors, if you pass something completely invalid for id_key
like "abc" for example, or omit it, it won't be added to values
, and the validation of user_id
will crash with KeyError: 'id_key'
, swallowing all the rest of the validation process and returning no sensible message.
user_dict = {'user_id': 10, 'id_key': 'abc'}
u = User(**user_dict)
# output:
# KeyError: 'id_key'
This is not very explicit, and might cause issues with your application if you expect a pydantic ValidationError
. You might want to check that id_key
is indeed present in values
and raise the error cleanly if not.
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)