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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:00:47