我想创建一个PYDANIC自定义字段.该验证器的主要目标是能够接受两种数据类型:"str"和"None".如果值为"None",则应返回空字符串.我试着这样做:

from pydantic import BaseModel


class EmptyStringField:
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if v is None:
            return ""
        return str(v)


class Model(BaseModel):
    url: EmptyStringField


model = Model(url=None)
print(model.url)

但是,我收到以下错误:

url
  none is not an allowed value (type=type_error.none.not_allowed)

推荐答案

如果您只想让url字段接受None作为特例,但是保存一个空字符串,那么您仍然应该将其声明为常规的str类型字段.您可以在定制的pre=True validator中处理特殊情况.那里不需要自定义数据类型.

from pydantic import BaseModel, validator


class Model(BaseModel):
    url: str

    @validator("url", pre=True)
    def none_to_empty(cls, v: object) -> object:
        if v is None:
            return ""
        return v


model = Model(url=None)
print(model.json())  # {"url": ""}

更新

如果不想在不同的模型中为不同的字段重复验证器,可以在自定义base model上定义一个通用的pre=True验证器,并实现某种逻辑来识别模型上的哪些字段要处理以及如何处理.

一种 Select 是利用typing.Annotated将任何给定的类型与一些应该调用的自定义转换函数"打包".然后,通用验证器将判断Annotated元数据的每个字段,如果找到一个函数,它将对该值调用该函数.

以下是一个有效的示例:

from typing import Annotated, get_origin

from pydantic import BaseModel as PydanticBaseModel, validator
from pydantic.fields import ModelField


class BaseModel(PydanticBaseModel):
    @validator("*", pre=True)
    def process_annotated(cls, v: object, field: ModelField) -> object:
        if get_origin(field.annotation) is not Annotated:
            return v
        func = field.annotation.__metadata__[0]
        if not callable(func):
            return v
        return func(v)


StrOrNone = Annotated[str, lambda v: "" if v is None else v]


class Model1(BaseModel):
    url: StrOrNone


print(Model1(url=None).json())  # {"url": ""}

Python相关问答推荐

产生镜像输出的MSG算法输出

将数组操作转化为纯numpy方法

在Docker中运行HAProxy时无法获得503服务

在Python中管理多个OpenGVBO和VAO实例

由于瓶颈,Python代码执行太慢-寻求性能优化

Python中是否有方法从公共域检索搜索结果

Pandas :多索引组

如何使用Google Gemini API为单个提示生成多个响应?

Python会扔掉未使用的表情吗?

三个给定的坐标可以是矩形的点吗

Select 用a和i标签包裹的复选框?

我在使用fill_between()将最大和最小带应用到我的图表中时遇到问题

TARete错误:类型对象任务没有属性模型'

通过Selenium从页面获取所有H2元素

将输入管道传输到正在运行的Python脚本中

Vectorize多个头寸的止盈/止盈回溯测试pythonpandas

Telethon加入私有频道

我如何使法国在 map 中完全透明的代码?

Scrapy和Great Expectations(great_expectations)—不合作

为什么numpy. vectorize调用vectorized函数的次数比vector中的元素要多?