Django自定义User模型TextChoices如何添加至表单ChoiceField并正常显示?
问题与解决方案
问题描述
自定义User模型中定义了Continents类型的TextChoices枚举选项,尝试将continents选项添加到表单中,通过{{ form }}渲染时出现报错:
TypeError: EnumType.__call__() missing 1 required positional argument: 'value'
此前在CustomUserCreationForm中用类似方式处理gender字段可正常工作。
错误原因
- 模型缺少对应字段:自定义User模型中仅定义了
Continents枚举类,但未添加实际存储值的continent字段(之前gender字段正常是因为模型中存在对应字段)。 - 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
相关产品推荐
相关产品推荐

