在 Pydantic 中定义递归模型?

Definining recursive models in Pydantic?

如何定义递归 Pydantic 模型?

这是我的意思的一个例子:

from typing import List
from pydantic import BaseModel

class Task(BaseModel):
    name: str
    subtasks: List[Task] = []

但是当我 运行 我得到以下错误:

NameError                                 Traceback (most recent call last)
<ipython-input-1-c6dca1d390fe> in <module>
      2 from pydantic import BaseModel
      3
----> 4 class Task(BaseModel):
      5     name: str
      6     subtasks: List[Task] = []

<ipython-input-1-c6dca1d390fe> in Task()
      4 class Task(BaseModel):
      5     name: str
----> 6     subtasks: List[Task] = []
      7

NameError: name 'Task' is not defined

我查看了文档,但没有找到任何内容。例如,在 "Recursive Models" 上的页面,但它似乎是关于 BaseModel 的嵌套子类型,而不是递归类型定义。

感谢您的帮助!

要么将 from __future__ import annotations 放在文件的顶部,要么将注释更改为 List['Task']

相关的 pydantic 文档在这里:https://pydantic-docs.helpmanual.io/usage/postponed_annotations/

但是你问题中的错误不是 pydantic 特有的,这就是类型注释的工作方式。

我发现自己处于一种情况,我想 运行 class 上的根验证器。 发生的情况是,尽管上述解决方案在某些情况下似乎有效,但递归字段 subtasks 的值并未出现在 @root_validatorvalues 字典参数中。

我最终宣布

subtasks: List[Dict]

并在 @root_validator 中递归构建子任务对象:

subtasks = values.get('subtasks')
if subtasks:
    values['subtasks']=[Task(**subtask) for subtask in subtasks]

扩展 Alex Hall 接受的答案:

从 Pydantic 文档来看,无论是否导入 annotations,似乎仍然需要调用 update_forward_refs()

from typing import List
from pydantic import BaseModel

class Task(BaseModel):
    name: str
    subtasks: List['Task'] = []


Task.update_forward_refs()

# python3.7+
from __future__ import annotations
from typing import List
from pydantic import BaseModel

class Task(BaseModel):
    name: str
    subtasks: List[Task] = []


Task.update_forward_refs()

https://pydantic-docs.helpmanual.io/usage/postponed_annotations/#self-referencing-models