Pydantic:使用文本验证区分并集

2024-09-30 01:22:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图使用Literal与Pydantic创建一个有区别的联盟。 有一些关于作业资源的事件,我想通过event_name来区分它们。对于JobPublishedEvents,我想确保存在一些extra_field

class GenericJobEvent(BaseModel):
    event_name: str
    id: int


class JobPublishedEvent(GenericJobEvent):
    event_name: Literal['job.published']
    extra_field: str


class Wrapper(BaseModel):
    wrapped: Union[JobPublishedEvent, GenericJobEvent]

print(type(Wrapper(wrapped={'event_name': 'some.event', 'id': 1}).wrapped))  # GenericJobEvent
print(type(Wrapper(wrapped={'event_name': 'job.published', 'id': 1, 'extra_field': 'extra'}).wrapped))  # JobPublishedEvent
print(type(Wrapper(wrapped={'event_name': 'job.published', 'id': 1}).wrapped))  # GenericJobEvent

前两种情况的行为与预期的一样,第三种情况我希望出现验证错误,因为文字匹配,但模式没有实现。不过,我明白了为什么对GenericJobEvent的回退是有效的

有人对如何实现这一目标有想法吗


Tags: nameeventidfieldtypejobwrapperextra
1条回答
网友
1楼 · 发布于 2024-09-30 01:22:55

这个问题是因为JobPublishedEvent失败了,而GenericJobEvent没有。想想看,event_name属性是一个字符串,id是一个int。所有内容都匹配

因此,您可以做的是验证GenericJobEvent中的event_name并拒绝事件名称job.published

您可以按照docs中的说明对其进行验证

@validator('event_name')
    def event_name_filter(cls, v):
        if 'job.published' == v:
            raise ValueError('GenericJobEvent cannot have event_name equal to job.published')
        return v.title()

相关问题 更多 >

    热门问题