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

Django自定义User模型TextChoices如何添加至表单ChoiceField并正常显示?

问题与解决方案

问题描述

自定义User模型中定义了Continents类型的TextChoices枚举选项,尝试将continents选项添加到表单中,通过{{ form }}渲染时出现报错:

TypeError: EnumType.__call__() missing 1 required positional argument: 'value'

此前在CustomUserCreationForm中用类似方式处理gender字段可正常工作。

错误原因

  1. 模型缺少对应字段:自定义User模型中仅定义了Continents枚举类,但未添加实际存储值的continent字段(之前gender字段正常是因为模型中存在对应字段)。
  2. Choices参数用法错误:直接将CustomUser.Continents枚举类传给ChoiceField的choices参数,正确做法是使用枚举类的choices属性,该属性会返回符合Django要求的(值, 显示文本)元组列表。

修正步骤

1. 完善CustomUser模型,添加continent字段

在Models.py中为CustomUser添加continent字段,关联定义好的Continents枚举:

class CustomUser(AbstractUser): #USER MODEL
    
    # CHOICES FOR USER CONTINENT
    class Continents(models.TextChoices):
        EUROPE = 'EUROPE' , 'EUROPE'
        AFRICA = 'AFRICA' , 'AFRICA'
        SOUTH_AMERICA = 'SOUTH AMERICA' , 'SOUTH AMERICA'
        NORTH_AMERICA = 'NORTH AMERICA' , 'NORTH AMERICA'
        OCEANIA = 'OCEANIA' , 'OCEANIA'
        ASIA = 'ASIA' , 'ASIA'
        
    username=None 

    nickname = models.CharField(max_length= 50, default = 'Not Set', blank=True)
    bio = models.TextField(max_length = 500 , blank=True , null= True , default= "Not Set")
    # 添加continent字段,关联枚举选项
    continent = models.CharField(
        max_length=20,
        choices=Continents.choices,
        default=Continents.EUROPE, # 可选:设置默认值
        blank=True
    )

    email = models.EmailField(max_length= 256 , unique=True) #USERS EMAIL ADDRESS

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    objects = UserManager()

2. 修正表单代码

应继承forms.ModelForm而非forms.Form(关联模型字段更便捷),并正确引用枚举的choices属性:

方式一:手动定义字段并指定widget

class CompleteProfileForm(forms.ModelForm):

    bio = forms.CharField(
        label='Bio: ',
        widget = forms.Textarea(
            attrs = {
                'class':'bioInput'
            }
        )
    )

    continent = forms.ChoiceField(
        label='Continents',
        choices=CustomUser.Continents.choices, # 使用枚举的choices属性
        widget = forms.Select(
            attrs = {
                'class':'continent',
                'id':'continent',
            } 
        )
    )

    class Meta:
        model = CustomUser
        fields = ['bio', 'continent']
        exclude = ['username']

方式二:利用ModelForm自动生成字段

如果不需要自定义widget,可直接通过Meta指定字段,Django会自动根据模型字段生成带正确选项的选择框:

class CompleteProfileForm(forms.ModelForm):

    bio = forms.CharField(
        label='Bio: ',
        widget = forms.Textarea(
            attrs = {
                'class':'bioInput'
            }
        )
    )

    class Meta:
        model = CustomUser
        fields = ['bio', 'continent']
        exclude = ['username']

说明

之前gender字段正常工作,是因为模型中存在gender字段,且表单中正确关联了模型;本次报错核心是缺少模型字段+枚举引用方式错误,修正后即可正常渲染选择框。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:58:25