rbh*_*lla 4 python python-typing pydantic
我正在尝试自动将 Pydantic 模型转换为数据库模式。为此,我递归地循环遍历 Pydantic 模型的字段以确定字段的类型。
作为一个例子,我有这个简单的模型:
from typing import List
from pydantic import BaseModel
class TestModel(BaseModel):
tags: List[str]
Run Code Online (Sandbox Code Playgroud)
__fields__我使用此处描述的属性递归模型: https ://docs.pydantic.dev/usage/models/#model-properties
如果我这样做,type(TestModel).__fields__['tags']我会看到:
ModelField(name='tags', type=List[str], required=True)
Run Code Online (Sandbox Code Playgroud)
我想以编程方式检查该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 Listtyping.get_origin(type(TestModel).__fields__['tags'].type_) == List令人沮丧的是,这确实返回True:
type(TestModel).__fields__['tags'].type_ is str我确认字段是List类型的正确方法是什么?
Pydantic 有场形状的概念。这些形状被编码为整数,并可作为模块中的常量使用fields。或多或少的标准类型已经被容纳在那里。如果一个字段被注释为list[T],那么shape该字段的属性将为SHAPE_LIST,并且type_将为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
Run Code Online (Sandbox Code Playgroud)
如果您想更深入地了解字段的实际注释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
Run Code Online (Sandbox Code Playgroud)
遗憾的是,据我所知,这些属性都没有在任何地方得到正式记录,但开源的美妙之处在于我们可以检查自己。属性和形状常量都不会以任何通常的方式被混淆、保护或设为私有,所以我假设它们是稳定的(至少在 Pydantic v2 下降之前)。
| 归档时间: |
|
| 查看次数: |
2945 次 |
| 最近记录: |