我有一个用Pydantic编写的嵌套模型。我在外部模型中有一个root_validator函数。我的印象是,如果外部根验证器被调用,那么内部模型是有效的。但显然不是。在下面的MWE中,我给内部模型指定了错误的字段名,但是外部验证器失败了:
from typing import List
from pydantic import BaseModel
from pydantic.class_validators import root_validator
class CarList(BaseModel):
cars: List[str]
colors: List[str]
class CarDealership(BaseModel):
name: str
cars: CarList
@root_validator()
def check_length(cls, v):
cars_list = v.get("cars")
if len(cars_list.cars) != len(cars_list.colors):
raise ValueError("wrong length")
return v
car_deal = {
"cars": {
"cars1": ["toyota", "tesla"],
"colors": ["white", "red"]
}
}
CarDealership.parse_obj(car_deal)我得到的错误是:
File "test.py", line 17, in check_length
if len(cars_list.cars) != len(cars_list.colors):
AttributeError: 'NoneType' object has no attribute 'cars'我希望是这样的:
pydantic.error_wrappers.ValidationError: 1 validation error for CarList
cars
field required (type=value_error.missing)如何确保内部模型首先得到验证?
发布于 2021-06-24 16:02:49
更新:外部类版本的验证
from typing import List
from pydantic import BaseModel
from pydantic.class_validators import root_validator
class CarList(BaseModel):
cars: List[str]
colors: List[str]
class CarDealership(BaseModel):
name: str
cars_list: CarList
@root_validator(pre=True)
def check_length(cls, v):
cars_list = v.get("cars_list")
if not cars_list:
return v
cars = cars_list.get("cars")
colors = cars_list.get("colors")
if not isinstance(cars, list) or not isinstance(colors, list):
return v
if cars is not None and colors is not None and len(cars) != len(colors):
raise ValueError("wrong length")
return vroot_validator默认的pre=False,内部模型已经验证过了,所以你得到了v == {}。
您可以在CarList中制作check_length,检查cars和colors是否存在(已经验证,失败则为无)。
from typing import List
from pydantic import BaseModel
from pydantic.class_validators import root_validator
class CarList(BaseModel):
cars: List[str]
colors: List[str]
@root_validator
def check_length(cls, v):
cars = v.get("cars")
colors = v.get("colors")
if cars is not None and colors is not None and len(cars) != len(colors):
raise ValueError("wrong length")
return v
class CarDealership(BaseModel):
name: str
car_list: CarList
car_deal_1 = {
"name": "value",
"car_list": {
"cars1": ["toyota", "tesla"],
"colors": ["white", "red"]
}
}
CarDealership.parse_obj(car_deal_1)
# pydantic.error_wrappers.ValidationError: 1 validation error for CarDealership
# car_list -> cars
# field required (type=value_error.missing)
car_deal_2 = {
"name": "value",
"car_list": {
"cars": ["toyota", "tesla"],
"colors": ["white", "red", "bule"]
}
}
CarDealership.parse_obj(car_deal_2)
# pydantic.error_wrappers.ValidationError: 1 validation error for CarDealership
# car_list -> __root__
# wrong length (type=value_error)发布于 2021-09-02 17:23:06
基于@YeJun响应,但假设您对响应的注释是您需要将内部类用于其他目的,您可以创建一个带有验证的中间类,同时保留原始CarList类用于其他用途:
from typing import List
from pydantic import BaseModel
from pydantic.class_validators import root_validator
class CarList(BaseModel):
cars: List[str]
colors: List[str]
# this class will have the same fields from CarList, but with validation
class CarListWithValidator(CarList):
@root_validator
def check_length(cls, v):
cars = v.get("cars")
colors = v.get("colors")
if cars is not None and colors is not None and len(cars) != len(colors):
raise ValueError("wrong length")
return v
class CarDealership(BaseModel):
name: str
car_list: CarListWithValidator
car_deal_2 = {
"name": "value",
"car_list": {
"cars": ["toyota", "tesla"],
"colors": ["white", "red", "bule"]
}
}
CarDealership.parse_obj(car_deal_2)
# pydantic.error_wrappers.ValidationError: 1 validation error for CarDealership
# car_list -> __root__
# wrong length (type=value_error)https://stackoverflow.com/questions/68082983
复制相似问题