首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Pydantic:验证嵌套模型

Pydantic:验证嵌套模型
EN

Stack Overflow用户
提问于 2021-06-22 19:46:37
回答 2查看 1.3K关注 0票数 0

我有一个用Pydantic编写的嵌套模型。我在外部模型中有一个root_validator函数。我的印象是,如果外部根验证器被调用,那么内部模型是有效的。但显然不是。在下面的MWE中,我给内部模型指定了错误的字段名,但是外部验证器失败了:

代码语言:javascript
复制
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)

我得到的错误是:

代码语言:javascript
复制
  File "test.py", line 17, in check_length
    if len(cars_list.cars) != len(cars_list.colors):
AttributeError: 'NoneType' object has no attribute 'cars'

我希望是这样的:

代码语言:javascript
复制
pydantic.error_wrappers.ValidationError: 1 validation error for CarList
cars
  field required (type=value_error.missing)

如何确保内部模型首先得到验证?

EN

回答 2

Stack Overflow用户

发布于 2021-06-24 16:02:49

更新:外部类版本的验证

代码语言:javascript
复制
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 v

root_validator默认的pre=False,内部模型已经验证过了,所以你得到了v == {}

您可以在CarList中制作check_length,检查carscolors是否存在(已经验证,失败则为无)。

代码语言:javascript
复制
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)
票数 0
EN

Stack Overflow用户

发布于 2021-09-02 17:23:06

基于@YeJun响应,但假设您对响应的注释是您需要将内部类用于其他目的,您可以创建一个带有验证的中间类,同时保留原始CarList类用于其他用途:

代码语言:javascript
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68082983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档