为什么我可以在pydantic列表中指定多种类型

发布于 2025-01-26 11:36:34 字数 2146 浏览 5 评论 0原文

class Embedded(BaseModel):
    path: str
    items: list[Union[ResourceItemDir, ResourceItemFile]] # here
    limit: int
    offset: int
    sort: str
    total: int

class ResourceItemFile(BaseModel):
    name: str
    path: str
    size: int
    file: str

    resource_id: str
    created: datetime.datetime
    modified: datetime.datetime
    media_type: str
    antivirus_status: str
    comment_ids: dict
    exif: dict
    md5: str
    mime_type: str
    preview: str
    revision: int
    sha256: str
    share: dict
    type: Literal["file"]

class ResourceItemDir(BaseModel):
    name: str
    path: str

    comment_ids: dict
    created: datetime.datetime
    exif: dict
    modified: datetime.datetime
    public_key: str
    public_url: str
    resource_id: str
    revision: int
    share: dict
    type: Literal["dir"]

为什么我不能在Pydantic列表中指定多种类型? 我还能如何指定项目字段接受两种数据类型? 如果有想法,我应该实施多么不同?

现在是一个错误:

  File "pydantic\main.py", line 331, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 99 validation errors for Resource
embedded -> items -> 2 -> public_key
  field required (type=value_error.missing)
embedded -> items -> 2 -> public_url
  field required (type=value_error.missing)
embedded -> items -> 2 -> size
  field required (type=value_error.missing)
embedded -> items -> 2 -> file
  field required (type=value_error.missing)
embedded -> items -> 2 -> media_type
  field required (type=value_error.missing)
embedded -> items -> 2 -> antivirus_status
  field required (type=value_error.missing)
embedded -> items -> 2 -> md5
  field required (type=value_error.missing)
embedded -> items -> 2 -> mime_type
  field required (type=value_error.missing)
embedded -> items -> 2 -> preview
  field required (type=value_error.missing)
embedded -> items -> 2 -> sha256
  field required (type=value_error.missing)
embedded -> items -> 2 -> type
  unexpected value; permitted: 'file' (type=value_error.const; given=dir; permitted=('file',))
class Embedded(BaseModel):
    path: str
    items: list[Union[ResourceItemDir, ResourceItemFile]] # here
    limit: int
    offset: int
    sort: str
    total: int

class ResourceItemFile(BaseModel):
    name: str
    path: str
    size: int
    file: str

    resource_id: str
    created: datetime.datetime
    modified: datetime.datetime
    media_type: str
    antivirus_status: str
    comment_ids: dict
    exif: dict
    md5: str
    mime_type: str
    preview: str
    revision: int
    sha256: str
    share: dict
    type: Literal["file"]

class ResourceItemDir(BaseModel):
    name: str
    path: str

    comment_ids: dict
    created: datetime.datetime
    exif: dict
    modified: datetime.datetime
    public_key: str
    public_url: str
    resource_id: str
    revision: int
    share: dict
    type: Literal["dir"]

Why can't I specify multiple types in a List in pydantic?
How else can I specify that the items field accepts two data types?
If there are ideas how differently I should implement it?

Now such a mistake:

  File "pydantic\main.py", line 331, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 99 validation errors for Resource
embedded -> items -> 2 -> public_key
  field required (type=value_error.missing)
embedded -> items -> 2 -> public_url
  field required (type=value_error.missing)
embedded -> items -> 2 -> size
  field required (type=value_error.missing)
embedded -> items -> 2 -> file
  field required (type=value_error.missing)
embedded -> items -> 2 -> media_type
  field required (type=value_error.missing)
embedded -> items -> 2 -> antivirus_status
  field required (type=value_error.missing)
embedded -> items -> 2 -> md5
  field required (type=value_error.missing)
embedded -> items -> 2 -> mime_type
  field required (type=value_error.missing)
embedded -> items -> 2 -> preview
  field required (type=value_error.missing)
embedded -> items -> 2 -> sha256
  field required (type=value_error.missing)
embedded -> items -> 2 -> type
  unexpected value; permitted: 'file' (type=value_error.const; given=dir; permitted=('file',))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡淡绿茶香 2025-02-02 11:36:34

我想我使用pedantic注释的解决方案

class AbstractResourceItem(BaseModel):
    name: str
    path: str
    comment_ids: dict
    created: datetime.datetime
    modified: datetime.datetime
    exif: dict
    resource_id: str
    revision: int
    share: dict
    public_key: Optional[str]
    public_url: Optional[str]


class ResourceItemFile(AbstractResourceItem):
    size: int
    file: str
    media_type: str
    antivirus_status: str
    md5: str
    mime_type: str
    preview: str
    sha256: str
    type: Literal["file"]


class ResourceItemDir(AbstractResourceItem):
    embedded: Optional["Embedded"]
    type: Literal["dir"]

#here
ResourceItem = Annotated[
    Union[ResourceItemDir, ResourceItemFile],
    Field(discriminator="type")
]


class Embedded(BaseModel):
    path: str
    items: list[ResourceItem]
    limit: int
    offset: int
    sort: str
    total: int

I think I found a solution using Annotated from pedantic

class AbstractResourceItem(BaseModel):
    name: str
    path: str
    comment_ids: dict
    created: datetime.datetime
    modified: datetime.datetime
    exif: dict
    resource_id: str
    revision: int
    share: dict
    public_key: Optional[str]
    public_url: Optional[str]


class ResourceItemFile(AbstractResourceItem):
    size: int
    file: str
    media_type: str
    antivirus_status: str
    md5: str
    mime_type: str
    preview: str
    sha256: str
    type: Literal["file"]


class ResourceItemDir(AbstractResourceItem):
    embedded: Optional["Embedded"]
    type: Literal["dir"]

#here
ResourceItem = Annotated[
    Union[ResourceItemDir, ResourceItemFile],
    Field(discriminator="type")
]


class Embedded(BaseModel):
    path: str
    items: list[ResourceItem]
    limit: int
    offset: int
    sort: str
    total: int
绅刃 2025-02-02 11:36:34

Python 3.10+以下方式可能有可能:

from pydantic import BaseModel

class User(BaseModel):
    friends: list[int | str] = []

u1 = User(friends=[1, 1, 'foo', 'bar', 1])

It is possible with python 3.10+ in the following way:

from pydantic import BaseModel

class User(BaseModel):
    friends: list[int | str] = []

u1 = User(friends=[1, 1, 'foo', 'bar', 1])
梦明 2025-02-02 11:36:34

从python 3.10,您可以使用以下方式使用联合类型

from unittest import TestCase
from pydantic import BaseModel


class F1(BaseModel):
    name: str


class F2(BaseModel):
    name: int


class User(BaseModel):
    friends: list[F1 | F2] = []


class TestPydanticFunctionality(TestCase):
    def test_allow_two_types(self):
        
        u1 = User(friends=[F2(name=1), F1(name="foo"), F2(name=1)])

        j = u1.model_dump_json()

        u2 = User.model_validate_json(j)

        self.assertTrue(isinstance(u2.friends[0], F2))
        self.assertTrue(isinstance(u2.friends[1], F1))
        self.assertTrue(isinstance(u2.friends[2], F2))

From Python 3.10 you can use Union types in the following way

from unittest import TestCase
from pydantic import BaseModel


class F1(BaseModel):
    name: str


class F2(BaseModel):
    name: int


class User(BaseModel):
    friends: list[F1 | F2] = []


class TestPydanticFunctionality(TestCase):
    def test_allow_two_types(self):
        
        u1 = User(friends=[F2(name=1), F1(name="foo"), F2(name=1)])

        j = u1.model_dump_json()

        u2 = User.model_validate_json(j)

        self.assertTrue(isinstance(u2.friends[0], F2))
        self.assertTrue(isinstance(u2.friends[1], F1))
        self.assertTrue(isinstance(u2.friends[2], F2))

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文