You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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是因为:

  1. EnumMixin初始化时默认使用models.Choices,而非你的FabricType枚举类
  2. FabricType的__new__方法参数与成员元组不匹配,导致枚举成员未被EnumMeta正确注册,无法通过数值获取实例

内容的提问来源于stack exchange,提问作者piscvau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 01:59:58