[英]Pydantic: How do I call a superclass method inside a subclass validator?
我正在尝试使用超类方法验证子类,但我做的事情根本上是错误的,无法弄清楚。
from pydantic import BaseModel, validator, root_validator
class Name(BaseModel):
name: str
def name_has_two_parts(self):
return len(self.name.split())==2
class FirstLast(Name):
@root_validator(pre=True)
@classmethod
def check_parts(cls, values):
#assert len(values["name"].split())==2 # <-- this works fine
assert super().name_has_two_parts(), f'Some message here' # <-- this does NOT work
return values
first_last = FirstLast(name="First Last")
有了这个我得到以下错误:
ValidationError: 1 validation error for FirstLast
__root__
name_has_two_parts() missing 1 required positional argument: 'self' (type=type_error)
任何帮助将不胜感激。 谢谢!
您的主要问题如下:
由于check_parts
是一个(根)验证器,它是一个class 方法。 (第一个参数称为cls
的事实也暗示了这一点。)这是正确的,因为这就是 Pydantic 验证器的工作方式。 它们在 model 实例完全初始化之前被调用。
但是,您的name_has_two_parts
方法是Name
class 的实例方法,inheritance 也是FirstLast
class 的实例方法。(第一个参数再次暗示self
。)这本身就很好,因为我假设您想使用它与Name
的实例一样,就像这样:
instance = Name(name="foo bar")
print(instance.name_has_two_parts()) # output: `True`
但是你不能从 class 调用它,即这不起作用:
Name.name_has_two_parts() # TypeError: Name.name_has_two_parts() missing 1 required positional argument: 'self'
没有self
可以提供,因为该调用中不存在任何实例。
然而,这正是您在 class 方法中所做的:
...
def check_parts(cls, values):
assert super().name_has_two_parts()
class 方法中的super
调用等效于super(FirstLast, cls).name_has_two_parts()
,这反过来导致name_has_two_parts
方法像我上面所做的那样在Name
class 上被调用。
一种可能的解决方案是将检查部件数量的逻辑分解到它自己的static方法中(因为它不依赖于任何 class 或实例属性),然后在实例方法和验证器中分别调用它:
from typing import Any
from pydantic import BaseModel, root_validator
class Name(BaseModel):
name: str
@staticmethod
def has_two_parts(string: str) -> bool:
return len(string.split()) == 2
def name_has_two_parts(self) -> bool:
return self.has_two_parts(self.name)
class FirstLast(Name):
@root_validator(pre=True)
def check_parts(cls, values: dict[str, Any]) -> dict[str, Any]:
assert cls.has_two_parts(values["name"]), "Some message here"
return values
if __name__ == '__main__':
first_last = FirstLast(name="First Last")
assert first_last.name_has_two_parts()
# wrong = FirstLast(name="First Last Third") # causes a `ValidationError`
作为旁注, @classmethod
装饰器不需要与@root_validator
(或常规的@validator
)一起使用。
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.