如何使用 pydantic 和 dict 数据类型创建动态模型

Posted

技术标签:

【中文标题】如何使用 pydantic 和 dict 数据类型创建动态模型【英文标题】:How to create dynamic models using pydantic and a dict data type 【发布时间】:2021-11-11 22:48:29 【问题描述】:

我正在尝试将 yml 文件加载到 dict 中,使用 pyyaml,加载过程会自动为我加载正确的类型,例如内容如下的 yml 文件:

key1: test
key2: 100

将被加载到"key1": "test", "key2":100 的dict 中,其中key1 的值类型为string,key2 值的类型为int

现在我想基于这个dict 动态创建一个类,基本上是一个以dict 键作为字段,dict 值作为值的类,如下所示:

class Test:
    key1: str = "test"
    key2: int = 100

我相信我可以使用Pydantic 执行以下操作:

Test = create_model('Test', key1=(str, "test"), key2=(int, 100))

但是,如此处所示,我必须手动告诉create_model 用于创建此模型的键和类型。不知道有没有办法自动使用dict中的项目来创建模型?

【问题讨论】:

【参考方案1】:

是的,例如,您可以为字典项递归调用create_model,传递键和值类型,值本身可以成为默认值。

示例(未准备好生产):

from typing import Dict
from pydantic import create_model

test_dict = 'a': 12, 'nested': 'b': 'value', 'c': 1


def _make_model(v, name):
    if type(v) is dict:
        return create_model(name, **k: _make_model(v, k) for k, v in v.items()), ...
    return type(v), v


def make_model(v: Dict, name: str):
    return _make_model(v, name)[0]


model = make_model(test_dict, 'MyModel')
m = model.parse_obj(test_dict)
print(m)
print(model.schema_json(indent=2))

输出:

a=12 nested=nested(b='value', c=1)


  "title": "MyModel",
  "type": "object",
  "properties": 
    "a": 
      "title": "A",
      "default": 12,
      "type": "integer"
    ,
    "nested": 
      "$ref": "#/definitions/nested"
    
  ,
  "required": [
    "nested"
  ],
  "definitions": 
    "nested": 
      "title": "nested",
      "type": "object",
      "properties": 
        "b": 
          "title": "B",
          "default": "value",
          "type": "string"
        ,
        "c": 
          "title": "C",
          "default": 1,
          "type": "integer"
        
      
    
  

【讨论】:

以上是关于如何使用 pydantic 和 dict 数据类型创建动态模型的主要内容,如果未能解决你的问题,请参考以下文章

从 dict 生成 pydantic 模型

pydantic学习与使用-1.pydantic简介与基础入门

如何在 FastAPI 中使用 Pydantic 模型和表单数据?

pydantic学习与使用-2.基本模型(BaseModel)使用

FastApi学习 Pydantic 做类型强制检查

flake8 和 Pydantic 约束类型的语法错误:constr(regex=)