【问题标题】:Creating Pydantic Model Schema with Dynamic Key使用动态键创建 Pydantic 模型模式
【发布时间】:2020-05-22 04:52:18
【问题描述】:

我正在尝试为以下 JSON 实现 Pydantic 模式模型。

{
    "description": "Best Authors And Their Books",
    "authorInfo":
    {
        "KISHAN":
            {
            "numberOfBooks": 10,
            "bestBookIds": [0, 2, 3, 7]
            },
        "BALARAM":
            {
            "numberOfBooks": 15,
            "bestBookIds": [10, 12, 14]
            },
        "RAM":
            {
            "numberOfBooks": 6,
            "bestBookIds": [3,5]

        }
    }
}

这是 Pydantic 中的模式对象

from typing import List, Type, Dict
from pydantic import BaseModel

class AuthorBookDetails(BaseModel):
    numberOfBooks: int
    bestBookIds: List[int]

class AuthorInfoCreate(BaseModel):
    __root__: Dict[str, Type[AuthorBookDetails]]    
#pass

class ScreenCreate(BaseModel):
    description: str
    authorInfo: Type[AuthorInfoCreate]

我正在解析 AuthorInfoCreate 如下:

y = AuthorBookDetails( numberOfBooks = 10, bestBookIds = [3,5])
print(y)
print(type(y))

x = AuthorInfoCreate.parse_obj({"RAM" : y})
print(x)

我看到以下错误。

numberOfBooks=10 bestBookIds=[3, 5]

<class '__main__.AuthorBookDetails'>

Traceback (most recent call last):

  File "test.py", line 44, in <module>

    x = AuthorInfoCreate.parse_obj({"RAM": y})

  File "C:\sources\rep-funds\env\lib\site-packages\pydantic\main.py", line 402, in parse_obj

    return cls(**obj)

  File "C:\sources\rep-funds\env\lib\site-packages\pydantic\main.py", line 283, in __init__

    raise validation_error

pydantic.error_wrappers.ValidationError: 1 validation error for AuthorInfoCreate

__root__ -> RAM

  subclass of AuthorBookDetails expected (type=type_error.subclass; expected_class=AuthorBookDetails)

我想了解如何更改 AuthorInfoCreate 以便我提到 json 架构。

【问题讨论】:

  • unhashable 类型错误是由于尝试从管道创建集合,与 pydantic 无关。
  • 我改变了我的问题,看看我到底在寻找什么。我想了解如何更改 AuthorInfoCreate 以便我提到 json 架构。
  • @navule 你找到解决方案了吗?
  • @SKhalymon 还没有。可能我需要尝试使用最新的 Pydantic 文档和线索。

标签: python fastapi pydantic


【解决方案1】:

实际上,您应该从类型注释中删除 Type。您需要一个类的实例,而不是一个实际的类。请尝试以下解决方案:

from typing import List,Dict
from pydantic import BaseModel

class AuthorBookDetails(BaseModel):
    numberOfBooks: int
    bestBookIds: List[int]

class AuthorInfoCreate(BaseModel):
    __root__: Dict[str, AuthorBookDetails]

class ScreenCreate(BaseModel):
    description: str
    authorInfo: AuthorInfoCreate

【讨论】:

  • 谢谢!在 Pydantic 模型中定义属性时,我误解了类型。
  • 如果我想要使用 AuthorBookDetails 作为基本模型的多个动态密钥,并且曾经让我们说 AuthorDetails。我不认为我们可以将两个模型都绑定到 root,在那种情况下你会怎么做
  • @Callmeashish 我不知道如何使用 Pydantic,但您可以查看 trafaret.readthedocs.io/en/latest/intro.html,它在验证方面比 Pydantic 做得更多。
【解决方案2】:

对于那些如何初始化 Pydantic 类的人,@SKhalymon 给出了答案,

from typing import List, Dict
from pydantic import BaseModel

class AuthorBookDetails(BaseModel):
    numberOfBooks: int
    bestBookIds: List[int]

class AuthorInfoCreate(BaseModel):
    __root__: Dict[str, AuthorBookDetails]

class ScreenCreate(BaseModel):
    description: str
    authorInfo: AuthorInfoCreate



kishan = AuthorBookDetails( numberOfBooks = 10, bestBookIds = [0, 2, 3, 7])

balram = AuthorBookDetails( numberOfBooks = 15, bestBookIds = [10, 12, 14])

ram = AuthorBookDetails( numberOfBooks = 6, bestBookIds = [3, 5])

aic = AuthorInfoCreate(__root__={"KISHAN": kishan, "BALRAM": balram, "RAM": ram})

sc = ScreenCreate( description = "Best Authors And Their Books", authorInfo = aic)

print(sc.json())

输出:

{"description": "Best Authors And Their Books", "authorInfo": {"__root__": {"KISHAN": {"numberOfBooks": 10, "bestBookIds": [0, 2, 3, 7]}, "BALRAM": {"numberOfBooks": 15, "bestBookIds": [10, 12, 14]}, "RAM": {"numberOfBooks": 6, "bestBookIds": [3, 5]}}}}

【讨论】:

    【解决方案3】:

    来自pydantic issue #2100

    __root__ 仅在父级支持。

    这就是为什么不能使用

    class AuthorInfoCreate(BaseModel):
        __root__: Dict[str, AuthorBookDetails]
    

    在上述问题中提出了以下解决方法

    from typing import Any, Dict, List
    
    from pydantic import BaseModel as PydanticBaseModel
    from pydantic.utils import ROOT_KEY
    
    
    class BaseModel(PydanticBaseModel):
        def __init__(__pydantic_self__, **data: Any) -> None:
            if __pydantic_self__.__custom_root_type__ and data.keys() != {ROOT_KEY}:
                data = {ROOT_KEY: data}
            super().__init__(**data)
    
    ...
    ...
    

    现在可以像往常一样使用AuthorInfoCreate模型了

    aic = AuthorInfoCreate(**{"KISHAN": kishan, "BALRAM": balram, "RAM": ram})
    

    PR #2237 应该使上述解决方法变得不必要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2020-07-04
      • 1970-01-01
      • 2015-05-20
      • 1970-01-01
      • 2021-01-29
      相关资源
      最近更新 更多