如何使用列表中的值作为 pydantic 验证器?
Posted
技术标签:
【中文标题】如何使用列表中的值作为 pydantic 验证器?【英文标题】:How to use values from list as pydantic validator? 【发布时间】:2021-04-04 12:18:58 【问题描述】:我想创建 pydantic 模型来验证用户表单。 我的模型值之一应该从名称列表中验证。 我成功使用枚举创建模型如下:
from enum import Enum
class Fruit(str, Enum):
APPLE = 'apple'
BANANA = 'banana'
MELON = 'melon'
from pydantic import BaseModel
class UserForm(BaseModel):
fruit: Fruit
name: str
现在我想将枚举切换到我的代码中的值列表:
fruit = ['apple','banana','melon']
我怎样才能做到这一点?
tnx
【问题讨论】:
【参考方案1】:我提出了一个优雅的解决方案。
from pydantic import BaseModel
from typing import List
from enum import Enum
class Fruit(str, Enum):
APPLE = 'apple'
BANANA = 'banana'
MELON = 'melon'
class UserForm(BaseModel):
fruits: List[Fruit]
name: str
就是这样。
您无需编写自己的验证器 告诉 pydantic 你需要一个 Fruit 对象的列表,它会为你做这件事查看上面的代码:
把上面的代码放到一个文件main.py
.
运行
python -i main.py
>>> uf = UserForm(fruits=['apple','banana'],name='hello')
>>> uf
UserForm(fruits=[<Fruit.APPLE: 'apple'>, <Fruit.BANANA: 'banana'>], name='hello')
>>> af = UserForm(fruits=['monkey','apple'],name='hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pydantic/main.py", line 400, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for UserForm
fruits -> 0
value is not a valid enumeration member; permitted: 'apple', 'banana', 'melon' (type=type_error.enum; enum_values=[<Fruit.APPLE: 'apple'>, <Fruit.BANANA: 'banana'>, <Fruit.MELON: 'melon'>])
>>>
pydantic 会引发错误,因为monkey
不在水果中。
【讨论】:
【参考方案2】:您也可以通过Literal
类型的列表来执行此操作。像这样:
import pydantic
from typing import Literal, List
class M(pydantic.BaseModel):
fruits: List[Literal["apple", "orange"]]
print(M.parse_obj("fruits":["apple", "orange"])) # OK fruits=['apple', 'orange']
print(M.parse_obj("fruits":["apple", "orange", "potato"])) # Error unexpected value potato
【讨论】:
【参考方案3】:您可以通过以下方式使用validator
:
from pydantic import BaseModel, ValidationError, validator
class UserForm(BaseModel):
fruit: str
name: str
@validator('fruit')
def fruit_must_be_in_fruits(cls,fruit):
fruits=['apple','banana','melon']
if fruit not in fruits:
raise ValueError(f'must be in fruits')
return fruit
try:
UserForm(fruit="apple",name="apple")
except ValidationError as e:
print(e)
如果不符合条件会引发验证错误。
【讨论】:
嗨,非常感谢。但它仍然无法按我的意愿工作。我在 fastapi 中使用这个 UserForm,这意味着虽然 swagger/docs 会在我使用枚举解决方案时自动为用户建议所有值,但它不会在此解决方案中建议它们。【参考方案4】:您可以通过其 .__members__
字典获取有关枚举的信息 - 不过在这里您可以简单地迭代它的键:
from enum import Enum
class Fruit(str, Enum):
APPLE = 'apple'
BANANA = 'banana'
MELON = 'melon'
# only need __members__ if you need more infos about it
print(Fruit.__members__)
# you do not need the __members__ if you just want the keys
print([name.lower() for name in Fruit])
输出:
# enums __members__ dictionary
'APPLE': <Fruit.APPLE: 'apple'>,
'BANANA': <Fruit.BANANA: 'banana'>,
'MELON': <Fruit.MELON: 'melon'>
# lower keys
['apple', 'banana', 'melon']
【讨论】:
以上是关于如何使用列表中的值作为 pydantic 验证器?的主要内容,如果未能解决你的问题,请参考以下文章
pydantic学习与使用-7.字段顺序field-ordering
Python/Pydantic - 使用带有 json 对象的列表