无法确定Pydantic模型中的字段类型是否为列表类型



我正在尝试自动将Pydantic模型转换为DB模式。为此,我将递归地遍历Pydantic模型的字段,以确定字段的类型。

作为一个例子,我有这个简单的模型:

from typing import List
from pydantic import BaseModel
class TestModel(BaseModel):
tags: List[str]

我使用__fields__属性递归地遍历模型,如下所述:https://docs.pydantic.dev/usage/models/#model-properties

如果我做type(TestModel).__fields__['tags'],我看到:

ModelField(name='tags', type=List[str], required=True)

我想以编程方式检查ModelField类型是否具有List起源。我尝试了以下方法,但都不起作用:

  • type(TestModel).__fields__['tags'].type_ is List[str]
  • type(TestModel).__fields__['tags'].type_ == List[str]
  • typing.get_origin(type(TestModel).__fields__['tags'].type_) is List
  • typing.get_origin(type(TestModel).__fields__['tags'].type_) == List

令人沮丧的是,这确实返回True:

  • type(TestModel).__fields__['tags'].type_ is str

我确认字段是List类型的正确方法是什么?

Pydantic有形状的概念田地的。这些形状被编码为整数,并在fields模块中作为常量可用。这里已经包含了或多或少的标准类型。如果一个字段用list[T]注释,那么该字段的shape属性将为SHAPE_LISTtype_T

type_指向元素类型在所有不是SHAPE_SINGLETON的上下文中,即容器类型。这就是为什么你在你的例子中得到str

因此,对于像list这样简单的东西,您可以简单地根据该常量检查形状:

from pydantic import BaseModel
from pydantic.fields import SHAPE_LIST

class TestModel(BaseModel):
tags: list[str]
other: tuple[str]

tags_field = TestModel.__fields__["tags"]
other_field = TestModel.__fields__["other"]
assert tags_field.shape == SHAPE_LIST
assert other_field.shape != SHAPE_LIST

如果您想更深入地了解实际的注释字段的值,存储在字段的annotation属性中。有了它,你应该能够做所有typing相关的分析,如get_origin

这意味着完成检查的另一种方式是:

from typing import get_origin
from pydantic import BaseModel

class TestModel(BaseModel):
tags: list[str]
other: tuple[str]

tags_field = TestModel.__fields__["tags"]
other_field = TestModel.__fields__["other"]
assert get_origin(tags_field.annotation) is list
assert get_origin(other_field.annotation) is tuple

遗憾的是,据我所知,这两个属性在任何地方都没有官方文档,但是开源的美妙之处在于我们可以自己检查。属性和形状常量都没有以任何通常的方式被混淆、保护或私有,所以我假设它们是稳定的(至少在Pydantic v2下降之前)。

丹尼尔的回答是更pydantic,回答你的OP,只是得到.annotationattr(或属性-方法?)在字段。

一样,

>>> class Foo(BaseModel):
...     x: Optional[dict[str,list[int]]]
...
>>> Foo.__fields__
... typing.Optional[dict[str, list[int]]]

然后通过访问注释的内部下标__args__

来做任何你想做的工作

相关内容

  • 没有找到相关文章