我正在try 将我的代码更新到PYDANIC v2,但在找到复制版本1中的自定义类型的好方法时遇到了困难.我将使用我的自定义日期类型作为示例.最初的实现和用法如下所示:

from datetime import date
from pydantic import BaseModel


class CustomDate(date):
    # Override POTENTIAL_FORMATS and fill it with date format strings to match your data
    POTENTIAL_FORMATS = []
    
    @classmethod
    def __get_validators__(cls):
        yield cls.validate_date
        
    @classmethod
    def validate_date(cls, field_value, values, field, config) -> date:
        if type(field_value) is date:
            return field_value
        return to_date(field.name, field_value, cls.POTENTIAL_FORMATS, return_str=False)

class ExampleModel(BaseModel):
    class MyDate(CustomDate):
        POTENTIAL_FORMATS = ['%Y-%m-%d', '%Y/%m/%d']
    dt: MyDate

我try 遵循下面列出的official docs和示例here,它基本上是有效的,但是info参数没有我需要的字段(datafield_name).try 访问它们时会出现AttributeError.

info.field_name
*** AttributeError: No attribute named 'field_name'

Annotated__get_pydantic_core_schema__方法都有这个问题

from datetime import date
from typing import Annotated

from pydantic import BaseModel, BeforeValidator
from pydantic_core import core_schema  

class CustomDate:
    POTENTIAL_FORMATS = []

    @classmethod
    def validate(cls, field_value, info):
        if type(field_value) is date:
            return field_value
        return to_date(info.field_name, field_value, potential_formats, return_str=False)

    @classmethod
    def __get_pydantic_core_schema__(cls, source, handler) -> core_schema.CoreSchema:
        return core_schema.general_plain_validator_function(cls.validate)


def custom_date(potential_formats):
    """
    :param potential_formats: A list of datetime format strings
    """
    def validate_date(field_value, info) -> date:
        if type(field_value) is date:
            return field_value
        return to_date(info.field_name, field_value, potential_formats, return_str=False)
    CustomDate = Annotated[date, BeforeValidator(validate_date)]
    return CustomDate


class ExampleModel(BaseModel):
    class MyDate(CustomDate):
        POTENTIAL_FORMATS = ['%Y-%m-%d', '%Y/%m/%d']
    dt: MyDate
    dt2: custom_date(['%Y-%m-%d', '%Y/%m/%d'])

如果我只是将validate_date函数作为常规的field_validator来包含,我会得到info,其中包含我需要的所有字段,只有在将它与自定义类型一起使用时,我才会看到这个问题.如何编写可以访问以前验证的字段和正在验证的字段的名称的自定义类型?

推荐答案

根据this feature request的说法,在v2中访问定制类型验证器中的info.datainfo.field_name目前是不可能的.

如果您只需要info.data,那么看起来您可以用core_schema.field_before_validator_function来定义您的验证器(我猜field_*个验证器都可以),尽管您需要组成一个字段名:

from dataclasses import dataclass
from typing import Annotated, List, Any, Callable


from pydantic import ValidationError, BaseModel, Field, BeforeValidator, field_validator, GetCoreSchemaHandler
from pydantic_core import core_schema, CoreSchema


def fn(v: str, info: core_schema.ValidationInfo, *args, **kwargs) -> str:
    try:
        print(f'Validating {info.field_name}')
        return info.data['use_this']
    except AttributeError as err:
        return 'No data'


class AsFieldB4Method(str):
    @classmethod
    def __get_pydantic_core_schema__(
        cls, source_type: Any, handler: GetCoreSchemaHandler, *args, **kwargs
    ) -> CoreSchema:
        return core_schema.field_before_validator_function(fn, 'not_the_real_field_name', core_schema.str_schema())


class MyModel(BaseModel):
    use_this: str
    core_schema_field_b4_method: AsFieldB4Method  # Partially works

从 comments 中可以看出,皮丹蒂克团队似乎想让它与非字段验证器一起工作,并使访问info.field_name成为可能,所以希望这能实现.当更改发生时,我会更新此答案,但请判断该链接,以防我错过它.

Python相关问答推荐

opencv Python稳定的图标识别

查找下一个值=实际值加上使用极点的50%

Polars:使用列值引用when / then表达中的其他列

如何使用scipy从频谱图中回归多个高斯峰?

韦尔福德方差与Numpy方差不同

Gekko:Spring-Mass系统的参数识别

有症状地 destruct 了Python中的regex?

如何让程序打印新段落上的每一行?

如何过滤包含2个指定子字符串的收件箱列名?

PyQt5,如何使每个对象的 colored颜色 不同?'

移动条情节旁边的半小提琴情节在海运

提取相关行的最快方法—pandas

让函数调用方程

基于多个数组的多个条件将值添加到numpy数组

为什么在FastAPI中创建与数据库的连接时需要使用生成器?

Odoo16:模板中使用的docs变量在哪里定义?

仅使用预先计算的排序获取排序元素

Python协议不兼容警告

比较两个有条件的数据帧并删除所有不合格的数据帧

为什么我的scipy.optimize.minimize(method=";newton-cg";)函数停留在局部最大值上?