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

Django表单更新数据报错:外键字段无法选择有效选项

Django外键表单更新异常排查与修复

问题现象

  • 新增Slotmodels记录时,categoryid、shopid、brandid三个外键字段正常渲染下拉选项列表,提交后能正确存储关联ID
  • 更新已有记录时,外键字段仅显示文本描述,无下拉选项;提交表单时触发验证错误:Select a valid choice. That choice is not one of the available choices.

相关代码

模型代码

class Slotmodels (models.Model):
    modelid = models.AutoField(primary_key=True)
    model_desc = models.TextField()
    categoryid = models.ForeignKey(categories, on_delete=models.CASCADE)
    shopid = models.ForeignKey(shops, on_delete=models.CASCADE)
    brandid = models.ForeignKey(brands, on_delete=models.CASCADE)
    reference = models.CharField(max_length=50,null=True)
    history = models.TextField(null=True)
    year = models.IntegerField(null=True)
    purchase_price = models.FloatField(default=0)
    actual_price = models.FloatField(default=0)
    limited_edition = models.BooleanField(null=False,default=False)
    color = models.CharField(max_length=50,null=True)
    number = models.IntegerField(null=True)
    livery = models.CharField(max_length=50,null=True)
    sponsor = models.CharField(max_length=50,null=True)
    scale = models.CharField(max_length=10,null=True)
    engine = models.CharField(max_length=20,null=True)
    eng_position = models.CharField(max_length=20,null=True)
    crown = models.IntegerField(null=True)
    pinion = models.IntegerField(null=True)
    crown_bnd = models.CharField(max_length=20,null=True)
    pinion_bnd = models.CharField(max_length=20,null=True)
    active = models.BooleanField(default=True)
    chasis = models.CharField(max_length=20,null=True)
    rear_axis = models.CharField(max_length=30,null=True)
    front_axis = models.CharField(max_length=30,null=True)
    front_tire_diam = models.IntegerField(null=True)
    rear_tire_diam = models.IntegerField(null=True)
    front_tire_width = models.IntegerField(null=True)
    rear_tire_width = models.IntegerField(null=True)
    collection_desc = models.CharField(max_length=30,null=True)
    bench_desc = models.CharField(max_length=30,null=True)
    Total_weight = models.IntegerField(null=True)
    
    
    def __str__(self):
        return self.modelid, self.model_desc

表单代码

class FormAltaSlotModel(ModelForm):
    class Meta:
        model = Slotmodels
        fields = ['modelid','model_desc','categoryid','shopid','brandid','reference','history','year','purchase_price',
                  'actual_price','limited_edition','color','number','livery','sponsor','scale','engine','eng_position',
                  'crown','pinion','crown_bnd','pinion_bnd','active','chasis','rear_axis','front_axis','front_tire_diam',
                  'rear_tire_diam','front_tire_width','rear_tire_width','collection_desc','bench_desc','Total_weight']
        help_texts = {
                
        }
        widgets = {
            'history': Textarea(attrs={'cols': 30, 'rows': 2}),
            'model_desc': Textarea(attrs={'cols': 30, 'rows': 2})
        }

修复方案

1. 修正Slotmodels的__str__方法

模型的__str__方法必须返回字符串,当前返回元组会导致表单渲染外键时出现异常。修改为:

def __str__(self):
    return f"{self.modelid} - {self.model_desc}"

2. 移除表单中的主键字段modelid

自增主键无需在表单中编辑,手动包含会干扰更新时的验证逻辑,从fields列表中删除modelid:

fields = ['model_desc','categoryid','shopid','brandid','reference','history','year','purchase_price',
          'actual_price','limited_edition','color','number','livery','sponsor','scale','engine','eng_position',
          'crown','pinion','crown_bnd','pinion_bnd','active','chasis','rear_axis','front_axis','front_tire_diam',
          'rear_tire_diam','front_tire_width','rear_tire_width','collection_desc','bench_desc','Total_weight']

3. 验证关联模型的__str__方法

确保categories、shops、brands三个关联模型的__str__方法返回合法字符串,例如:

class categories(models.Model):
    # 你的字段定义
    def __str__(self):
        return self.category_name  # 替换为模型中实际的描述字段

4. 确认更新视图的表单初始化逻辑

更新视图必须传入要修改的实例对象,确保表单正确加载现有数据:

def update_slotmodel(request, pk):
    slot_instance = Slotmodels.objects.get(pk=pk)
    if request.method == 'POST':
        form = FormAltaSlotModel(request.POST, instance=slot_instance)
        if form.is_valid():
            form.save()
            # 重定向到记录详情页或列表页
            return redirect('slotmodel_detail', pk=slot_instance.modelid)
    else:
        form = FormAltaSlotModel(instance=slot_instance)
    return render(request, 'your_update_template.html', {'form': form})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 17:20:43