使用Django表单添加数据遇验证错误的解决求助
Django表单提交报错:"Select a valid choice. That choice is not one of the available choices." 解决方案
问题说明
提交Django表单时弹出错误提示:"Select a valid choice. That choice is not one of the available choices."。现有代码中,forms.py里的ModelChoiceField使用Product.objects.values_list('product_name', flat=True)作为查询集导致验证失败;替换为Category.objects.all()这类完整模型查询集时表单可正常提交,但需求是展示Product模型的product_name字段作为下拉选项。
原因分析
ModelChoiceField默认绑定模型实例,提交时会用模型主键(通常是整数ID)作为验证依据,显示内容由模型的__str__方法决定。- 使用
values_list('product_name', flat=True)返回的是字符串列表,提交时Django会尝试将该字符串匹配为Product的主键,自然匹配失败,触发验证错误。
解决方案
直接使用完整的Product模型查询集,通过自定义方法指定下拉选项显示product_name字段,无需修改查询集结构。
1. 修改forms.py代码
class AddForm(forms.Form): uploader_mail = forms.EmailField( label='Owner mail', initial='test@test.test', widget=forms.EmailInput(attrs={'class': 'form-control'})) body = forms.CharField( label='Data line by line', widget=forms.Textarea(attrs={'class': 'form-control','wrap': "off", })) # 使用完整Product查询集,自定义下拉显示文本 category = forms.ModelChoiceField( queryset=Product.objects.all(), label='Category', empty_label=None, widget=forms.Select(attrs={'class': 'form-select'})) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 指定下拉选项显示product_name self.fields['category'].label_from_instance = lambda obj: obj.product_name
2. 修正Product模型的__str__方法
当前__str__返回元组会导致显示异常,改为直接返回product_name:
class Product(models.Model): # 保留原有字段定义 product_name = models.CharField(max_length=400) description = models.CharField(max_length=4096) price = models.DecimalField(max_digits=8, decimal_places=2) geo = models.CharField(max_length=2) product_logo = models.ImageField(upload_to='img/logos', blank=True) category = models.ForeignKey('Category', on_delete=models.PROTECT) def __str__(self): return self.product_name
3. 完善视图逻辑(可选)
提交表单创建Account实例时,直接使用cleaned_data中的Product对象:
def edit(request): if request.method == 'POST': form = AddForm(request.POST) if form.is_valid(): cleaned_data = form.cleaned_data # 创建Account记录 Account.objects.create( uploader_mail=cleaned_data['uploader_mail'], body=cleaned_data['body'], product=cleaned_data['category'] ) else: form = AddForm() return render(request, 'goods_list/edit.html', {'form': form})
内容的提问来源于stack exchange,提问作者Evgeniy
相关产品推荐
相关产品推荐

