Another option is to just use @validator
because in it you can access previously validated fields. From the documentation:
- validators are "class methods", so the first argument value they receive is the UserModel class, not an instance of UserModel.
- the second argument is always the field value to validate; it can be named as you please
- you can also add any subset of the following arguments to the signature (the names must match):
values
: a dict containing the name-to-value mapping of any previously-validated fields
Example:
class Wallet(BaseModel):
private_key: str = Field(default_factory=key.generate_private_key)
address: str = "" # "" seems better than None to use the correct type
@validator("address", always=True)
def get_address(cls, address: str, values: Dict[str, Any]) -> str:
if address == "" and "private_key" in values:
return key.generate_address(values["private_key"])
return address
It can be argued that @validator
should be preferred over @root_validator
if you just want to generate a value for a single field.
There are two important aspects of this approach that must be considered:
The "previously-validated fields" from the documentation means that in your case private_key
must be defined before address
. The values of fields defined after the field that is validated are not available to the validator.
If the field that is validated has a default value and you still want the validator to be executed in that case, you have to use always=True
.