我正在try 创建一个接受某种格式的字符串日期时间的模型,但如果字符串值是空字符串"",则它应该在模型中作为类型无.

我正在使用BeforeGuardator,我认为这是正确的做法.

使用下面的代码,我希望parse_datetime函数返回无类型,然后将其传递给pydantic验证器.

有人能带领我走向正确的方向吗?

from pydantic import (
    BaseModel,
    Field,
    ValidationError,
    BeforeValidator,
)
from typing import Annotated, Any, Union
from datetime import datetime, date


def parse_datetime(value: str):
    print(len(value.strip()))
    if len(value.strip()) > 0:
        try:
            return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
        except Exception as e:
            raise ValueError(str(e))
    else:
        print("returning None")
        value = None
        return value


date_time = Annotated[datetime, BeforeValidator(parse_datetime)]


class Model(BaseModel):
    dt: date_time | None

使用空字符串时,我会出现验证错误

data = {"dt": ""}
try:
    Model.model_validate(data)
except ValidationError as e:
    print(e)
1 validation error for Model
dt
  Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]

然而传递它"无"类型有效

data = {"dt": None}

try:
    Model.model_validate(data)
except ValidationError as e:
    print(e)

推荐答案

我也很困惑为什么这不起作用.原因是BeforeValidator运行before内部验证逻辑(参见docs).如果您采用了运行内部验证逻辑insteadPlainValidator(参见docs),那么它就可以正常工作.

因此BeforeValidator的问题在于注释的类型.您仅在数据类型datetime上调用BeforeValidator(Annotated[datetime, ...]).因此内部验证逻辑仅接受datetime而不是None.

如果将注释更改为Annotated[datetime | None, BeforeValidator(parse_datetime)],它就会正常工作.

from pydantic import (
    BaseModel,
    BeforeValidator,
)
from typing import Annotated
from datetime import datetime


def parse_datetime(value: str):

    if value.strip():
        try:
            return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
        except Exception as e:
            raise ValueError(str(e))
    else:
        return None


date_time = Annotated[datetime | None, BeforeValidator(parse_datetime)]


class Model(BaseModel):
    dt: date_time

Model.model_validate({'dt': ' '})
# Model(dt=None)

Python相关问答推荐

使用from_pandas将GeDataFrame转换为polars失败,ArrowType错误:未传递numpy. dype对象

剧作家Python:expect(locator).to_be_visible()vs locator.wait_for()

如何在Python中使用io.BytesIO写入现有缓冲区?

将图像拖到另一个图像

如何在python xsModel库中定义一个可选[December]字段,以产生受约束的SON模式

如何在python polars中停止otherate(),当使用when()表达式时?

如何在Raspberry Pi上检测USB并使用Python访问它?

为什么抓取的HTML与浏览器判断的元素不同?

从一个系列创建一个Dataframe,特别是如何重命名其中的列(例如:使用NAs/NaN)

Stacked bar chart from billrame

无法连接到Keycloat服务器

如何使用两个关键函数来排序一个多索引框架?

如何使用使用来自其他列的值的公式更新一个rabrame列?

OpenCV轮廓.很难找到给定图像的所需轮廓

交替字符串位置的正则表达式

用SymPy在Python中求解指数函数

如何从pandas DataFrame中获取. groupby()和. agg()之后的子列?

如何在Python中将超链接添加到PDF中每个页面的顶部?

如何训练每一个pandaprame行的线性回归并生成斜率

为什么在Python中00是一个有效的整数?