如何在验证错误中从 loc 中删除鉴别器值?

问题描述 投票:0回答:1

我使用 Pydantic v2。现在我想从

loc
或验证错误中删除鉴别器值。请看下面的代码:

from pprint import pprint
from typing import Literal, Union, Annotated, Any

from pydantic import BaseModel, Field, RootModel, ValidationError
from pydantic.main import Model


class Tiger(BaseModel):
    animal_type: Literal["tiger"] = "tiger"
    ferocity_scale: float = Field(..., ge=0, le=10)


class Shark(BaseModel):
    animal_type: Literal["shark"] = "shark"
    ferocity_scale: float = Field(..., ge=0, le=10)


class Lion(BaseModel):
    animal_type: Literal["lion"] = "lion"
    ferocity_scale: float


class WildAnimal(RootModel):
    root: Annotated[Union[Tiger, Shark, Lion], Field(..., discriminator='animal_type')]


try:
    my_shark = WildAnimal.model_validate({'animal_type': 'shark', 'ferocity_scale': 115})
except ValidationError as exc:
    pprint(exc.errors())

代码打印:

[{'ctx': {'le': 10.0},
  'input': 115,
  'loc': ('shark', 'ferocity_scale'),  <------ how to drop "shark"?
  'msg': 'Input should be less than or equal to 10',
  'type': 'less_than_equal',
  'url': 'https://errors.pydantic.dev/2.7/v/less_than_equal'}]

loc
键中,您可以注意到
('shark', 'ferocity_scale')
。值
shark
是鉴别器
animal_type
值。

如何通过Pydantic删除它?或者如何动态检测

loc
的第一个值是鉴别器值?

我唯一能弄清楚的是:

class WildAnimal(RootModel):
    root: Annotated[Union[Tiger, Shark, Lion], Field(..., discriminator='animal_type')]

    @classmethod
    def model_validate(cls: type[Model], obj: Any, *, strict: bool | None = None, from_attributes: bool | None = None,
                       context: dict[str, Any] | None = None) -> Model:
        try:
            return super().model_validate(obj, strict=strict, from_attributes=from_attributes, context=context)
        except ValidationError as exc:
            # modify loc
            # reraise ValidationError
python pydantic-v2
1个回答
0
投票

必须实现装饰器:

def reconstruct_validation_error(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except ValidationError as e:
            errors = e.errors()
            for error in errors:
                error["loc"] = tuple(list(error["loc"])[1:])
            title, _ = func.__qualname__.split(".", maxsplit=1)
            raise ValidationError.from_exception_data(title=title, line_errors=errors)
    return wrapper


class WildAnimal(RootModel):
    root: Annotated[
        Union[Tiger, Shark, Lion],
        Field(..., discriminator='animal_type'),
    ]

    @reconstruct_validation_error
    def __init__(self, /, root: RootModelRootType = PydanticUndefined, **data) -> None:
        super().__init__(root, **data)
© www.soinside.com 2019 - 2024. All rights reserved.