如何声明受运行时确定列表约束的Pydantic字段?
解决Pydantic v1.10运行时动态约束字段可选值的问题
错误原因
你遇到的TypeError: unhashable type: 'list'是因为Literal类型要求传入哈希可比较的字面量/常量,而你直接将运行时生成的列表conversion传入Literal,列表属于不可哈希类型,导致Pydantic无法生成对应的验证器。
解决方案
方法一:将动态列表转为元组,构建Literal类型
元组是哈希可比较类型,只需在类定义前将获取到的列表转为元组,再传入Literal即可,这种方式和status字段的约束逻辑完全一致,同时保留类型提示。
from typing import Literal, Tuple from pydantic import BaseModel, Field from connectors.snowflake.snowflake_connector import SnowflakeConnector # 获取运行时可选值并转为元组 conversion_list = SnowflakeConnector().get_conversion()["conversion_name"].tolist() conversion_tuple = tuple(conversion_list) class MyModel(BaseModel): code: int = Field(alias="Code", frozen=True) status: Literal["Active", "Inactive"] = Field(alias="Status") conversion: Literal[conversion_tuple] = Field(alias="Conversion")
方法二:自定义验证器(更灵活)
如果需要动态更新可选值或添加复杂验证逻辑,可使用Pydantic的@validator装饰器自定义验证规则,检查输入值是否在允许的列表内。
from typing import Any from pydantic import BaseModel, Field, validator from connectors.snowflake.snowflake_connector import SnowflakeConnector # 获取运行时允许的可选值列表 allowed_conversions = SnowflakeConnector().get_conversion()["conversion_name"].tolist() class MyModel(BaseModel): code: int = Field(alias="Code", frozen=True) status: Literal["Active", "Inactive"] = Field(alias="Status") conversion: str = Field(alias="Conversion") @validator("conversion") def check_conversion_valid(cls, v: Any) -> Any: if v not in allowed_conversions: raise ValueError(f"conversion必须是以下值之一:{allowed_conversions}") return v
两种方法对比
- 方法一:保留
Literal的静态类型提示,IDE可识别可选值,验证逻辑由Pydantic自动处理,行为和status字段完全一致。 - 方法二:支持动态更新可选值列表,可扩展复杂验证逻辑,但失去
Literal的静态类型提示能力。
内容的提问来源于stack exchange,提问作者HuLu ViCa
相关产品推荐
相关产品推荐

