根据另一个值设置默认值

Setting a default value based on another value

我有以下 Pydantic 模型:

from pydantic import BaseModel
import key

class Wallet(BaseModel):
    private_key: str = Field(default_factory=key.generate_private_key)
    address: str

我希望地址有一个 default_factory 作为一个函数,它接受一个 private_key 作为输入和 returns 一个地址。我的意图大致如下:

address: str = Field(default_factory=key.generate_address(self.private_key)

我怎样才能做到这一点?

我能够使用 root_validator:

实现它
class Wallet(BaseModel):
    address: str = None
    private_key: str = Field(default_factory=key.generate_private_key)

    @root_validator
    def get_address(cls, values) -> dict:
        if values.get("address") is None:
            values["address"] = key.generate_address(values.get("private_key"))
        return values

不确定这是否是通过

实现此目的的最佳方式

另一种选择是仅使用 @validator,因为您可以在其中访问之前验证过的字段。来自 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

示例:

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 is None:
            return key.generate_address(values["private_key"])
        return address

如果您只想为单个字段生成一个值,可以说 @validator 应该优于 @root_validator

必须考虑此方法的两个重要方面:

  1. 文档中的“先前验证的字段”意味着在您的情况下 private_key 必须在 address 之前定义。在验证的字段之后定义的字段值对验证器不可用。

  2. 如果验证的字段有默认值,而你仍然希望在这种情况下执行验证器,则必须使用always=True.