[英]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.