[英]How to validate more than one field of pydantic model
我想驗證 pydantic model 的三個 model 字段。 為此,我從 pydantic 導入 root_validator。 低於錯誤。 我在https://pydantic-docs.helpmanual.io/usage/validators/#root-validators中找到了這個。 任何人都可以幫助我。 找出下面的錯誤。 from pydantic import BaseModel, ValidationError, root_validator Traceback(最近一次調用最后一次):文件“”,第 1 行,在 ImportError 中:無法從“pydantic”導入名稱“root_validator”(C:\Users\Lenovo\AppData\Local\Programs\ Python\Python38-32\lib\site-packages\pydantic__init__.py)
我試過了
@validator
def validate_all(cls,v,values,**kwargs):
我從一些常見的字段父 model 繼承了我的 pydantic model。 值僅顯示父 class 字段,但不顯示我的子 class 字段。 例如
class Parent(BaseModel):
name: str
comments: str
class Customer(Parent):
address: str
phone: str
@validator
def validate_all(cls,v,values, **kwargs):
#here values showing only (name and comment) but not address and phone.
您需要將字段作為裝飾器的 arguments 傳遞。
class Parent(BaseModel):
name: str
comments: str
class Customer(Parent):
address: str
phone: str
@validator("name", "coments", "address", "phone")
def validate_all(cls, v, values, **kwargs):
首先,如果您在導入root_validator時出錯,我會更新 pydantic。
pip install -U pydantic
上面的許多示例向您展示了如何一次對多個值使用相同的驗證器。 或者他們增加了很多不必要的復雜性來完成你想要的。 您可以簡單地使用以下代碼,使用root_validator裝飾器在同一個驗證器中同時驗證多個字段:
from pydantic import root_validator
from pydantic import BaseModel
class Parent(BaseModel):
name: str = "Peter"
comments: str = "Pydantic User"
class Customer(Parent):
address: str = "Home"
phone: str = "117"
@root_validator
def validate_all(cls, values):
print(f"{values}")
values["phone"] = "111-111-1111"
values["address"] = "1111 Pydantic Lane"
print(f"{values}")
return values
Output:
{'name': 'Peter', 'comments': 'Pydantic User', 'address': 'Home', 'phone': '117'}
{'name': 'Peter', 'comments': 'Pydantic User', 'address': '1111 Pydantic Lane', 'phone': '111-111-1111'}
為了擴展Rahul R
的答案,這個例子更詳細地展示了如何使用pydantic
驗證器。
此示例包含回答您的問題所需的所有信息。
import pydantic
class Parent(pydantic.BaseModel):
name: str
comments: str
class Customer(Parent):
address: str
phone: str
# If you want to apply the Validator to the fields "name", "comments", "address", "phone"
@pydantic.validator("name", "comments", "address", "phone")
@classmethod
def validate_all_fields_one_by_one(cls, field_value):
# Do the validation instead of printing
print(f"{cls}: Field value {field_value}")
return field_value # this is the value written to the class field
# if you want to validate to content of "phone" using the other fields of the Parent and Child class
@pydantic.validator("phone")
@classmethod
def validate_one_field_using_the_others(cls, field_value, values, field, config):
parent_class_name = values["name"]
parent_class_address = values["address"] # works because "address" is already validated once we validate "phone"
# Do the validation instead of printing
print(f"{field_value} is the {field.name} of {parent_class_name}")
return field_value
Customer(name="Peter", comments="Pydantic User", address="Home", phone="117")
Output
<class '__main__.Customer'>: Field value Peter
<class '__main__.Customer'>: Field value Pydantic User
<class '__main__.Customer'>: Field value Home
<class '__main__.Customer'>: Field value 117
117 is the phone number of Peter
Customer(name='Peter', comments='Pydantic User', address='Home', phone='117')
要更詳細地回答您的問題:
將要驗證的字段添加到驗證@validator
正上方的 @validator 裝飾器。
@validator("name")
使用 " "name"
" 的字段值(例如"Peter"
)作為驗證 function 的輸入。 class 及其父類的所有字段都可以添加到@validator
裝飾器中。validate_all_fields_one_by_one
) 然后使用字段值作為第二個參數 ( field_value
) 來驗證輸入。 驗證 function 的返回值寫入 class 字段。 驗證 function 的簽名是def validate_something(cls, field_value)
其中 function 和變量名稱可以任意選擇(但第一個參數應該是cls
)。 根據 Arjan ( https://youtu.be/Vj-iU-8_xLs?t=329 ),還應該添加@classmethod
裝飾器。 如果目標是通過使用父子 class 的其他(已驗證)字段來驗證一個字段,則驗證 function 的完整簽名是def validate_something(cls, field_value, values, field, config)
(參數名稱values
, field
和config
必須匹配)可以使用字段名稱作為鍵訪問字段的值(例如values["comments"]
)。
此示例包含回答您的問題所需的所有信息。
class User(BaseModel):
name: Optional[str] = ""
class Config:
validate_assignment = True
@validator("name")
def set_name(cls, name):
return name or "foo"
根據文檔,“可以通過傳遞多個字段名稱將單個validator
應用於多個字段”(並且“也可以通過傳遞特殊值'*'
在所有字段上調用”)。 因此,您可以將希望驗證的字段添加到validator
裝飾器,並使用field.name
屬性,您可以檢查每次調用validator
器時要驗證的字段。 如果一個字段沒有通過驗證,您可以raise ValueError
,“這將被捕獲並用於填充ValidationError
”(請參閱此處的“注意”部分)。 如果您需要根據其他字段驗證字段,則必須首先檢查它們是否已經使用values.get()
方法進行了驗證,如本答案所示(更新 2) 。 下面演示了一個示例,其中驗證了name
、 country_code
和phone
號碼等字段(基於提供的country_code
)。 提供的正則表達式模式只是本演示的示例,並且基於這個和這個答案..
from pydantic import BaseModel, validator
import re
name_pattern = re.compile(r'[a-zA-Z\s]+$')
country_codes = {"uk", "us"}
UK_phone_pattern = re.compile(r'^(\+44\s?7\d{3}|\(?07\d{3}\)?)\s?\d{3}\s?\d{3}$') # UK mobile phone number. Valid example: +44 7222 555 555
US_phone_pattern = re.compile(r'^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$') # US phone number. Valid example: (123) 123-1234
phone_patterns = {"uk": UK_phone_pattern, "us": US_phone_pattern}
class Parent(BaseModel):
name: str
comments: str
class Customer(Parent):
address: str
country_code: str
phone: str
@validator("name", "country_code", "phone")
def validate_atts(cls, v, values, field):
if field.name == "name":
if not name_pattern.match(v): raise ValueError(f'{v}" is not a valid name.')
elif field.name == "country_code":
if not v.lower() in country_codes: raise ValueError(f'{v} is not a valid country code.')
elif field.name == "phone" and values.get('country_code'):
c_code = values.get('country_code').lower()
if not phone_patterns[c_code].match(v): raise ValueError(f'{v} is not a valid phone number.')
return v
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.