Django中为IntegerChoices扩展额外数据遇ValueError问题求助
问题修复方案
1. 修正自定义枚举类FabricType的错误
你的FabricType类存在参数不匹配、变量未定义、语法错误等问题,直接导致枚举成员无法被正确识别:
class FabricType(models.IntegerChoices): """带额外数据的枚举类: 元组元素顺序: 1. 数据库存储值 2. 显示名称(已翻译) 3. 帮助文本(已翻译) 4. 分组标识 5. 关键词列表 修改数值需要数据库迁移,新增关键词无需迁移 """ CASTON = (1, _('Caston'), _('the first few rows of a knit'), _('Basic'), []) JERSEY = (2, _('Jersey'), _('help_text'), _('Basic'), []) TUBULAR = (3, _('Tubular'), _('help text'), _('Basic'), []) def __new__(cls, value, label, help_text, group, keywords): obj = int.__new__(cls, value) obj._value_ = value obj.label = label obj.help_text = help_text obj.group = group obj.keywords = keywords return obj @classmethod def help_dict(cls): """返回各枚举项的帮助文本字典""" return { member.name: member.help_text for member in cls }
- 对齐
__new__方法参数与枚举成员元组的顺序,明确每个元素的作用 - 修复了未定义的
help变量问题,改为help_text与元组对应 - 通过遍历枚举成员自动生成
help_dict,避免硬编码维护成本
2. 修正EnumMixin的枚举绑定逻辑
错误核心是EnumMixin默认使用models.Choices而非你的自定义枚举类,同时转换逻辑缺少容错:
class EnumMixin: """将数据库值转换为对应枚举实例的Mixin""" def __init__(self, *args, enum=None, **kwargs): # 强制要求传入自定义枚举类,避免默认值混淆 self.__enum = enum self.help_dict = kwargs.pop('help_dict', enum.help_dict() if enum else None) # 自动传递枚举的choices给父类字段 kwargs['choices'] = enum.choices if enum else kwargs.get('choices') super().__init__(*args, **kwargs) def deconstruct(self): name, path, args, kwargs = super().deconstruct() if self.__enum: kwargs['enum'] = self.__enum if self.help_dict: kwargs['help_dict'] = self.help_dict kwargs.pop('choices', None) return name, path, args, kwargs def __to_enum(self, value): if value is None: return None # 兼容整数、字符串形式的值,增加错误容错 try: return self.__enum(int(value)) except ValueError: try: return self.__enum[value] except KeyError: return value def from_db_value(self, value, expression, connection): return self.__to_enum(value) def to_python(self, value): # 已为枚举实例时直接返回,避免重复转换 if isinstance(value, self.__enum): return value return self.__to_enum(value)
- 移除
models.Choices默认值,强制关联自定义枚举类 - 优化
__to_enum方法,支持值、名称两种转换方式,增加错误处理 - 自动注入枚举的
choices配置,简化字段使用
3. 修正FabricTypeField的定义
让自定义字段默认绑定FabricType枚举,无需每次手动传入:
class FabricTypeField(EnumMixin, models.SmallIntegerField): def __init__(self, *args, **kwargs): # 默认绑定FabricType枚举 kwargs.setdefault('enum', FabricType) super().__init__(*args, **kwargs)
错误原因说明
你遇到的ValueError: 2 is not a valid Choices是因为:
EnumMixin初始化时默认使用models.Choices,而非你的FabricType枚举类FabricType的__new__方法参数与成员元组不匹配,导致枚举成员未被EnumMeta正确注册,无法通过数值获取实例
内容的提问来源于stack exchange,提问作者piscvau
相关产品推荐
相关产品推荐

