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
相关产品推荐
相关产品推荐

