Django表单提交新增数据库行而非更新现有数据,求排查错误
问题原因及解决方法
1. 视图处理POST请求时未绑定要修改的实例
当前视图处理POST请求时,直接用TrafficSourcesForm(request.POST)创建表单,没有传入对应要修改的instance参数。Django的ModelForm如果不指定instance,调用save()时默认会创建新对象,而非修改现有记录。
修复视图代码:
需要从POST请求中获取目标对象的ID,绑定到表单的instance参数上:
def settings(request): error = '' if request.method == 'POST': # 获取要修改的对象ID(假设模型主键为id) obj_id = request.POST.get('id') try: # 根据ID获取对应实例 target_obj = TrafficSources.objects.get(id=obj_id) # 绑定实例到表单,明确是修改操作 new_form = TrafficSourcesForm(request.POST, instance=target_obj) if new_form.is_valid(): new_form.save() except TrafficSources.DoesNotExist: error = '目标记录不存在!' else: error = '请求方式错误!' # 注意缩进,原代码此处缩进错误 new_form = TrafficSourcesForm() forms = [TrafficSourcesForm(instance=x) for x in TrafficSources.objects.all()] return render(request, 'mainpage/dashboard.html', {'new_form': new_form, 'forms': forms, 'error': error})
2. 模板表单缺少主键隐藏字段
当前模板的表单没有传递目标对象的主键ID,导致视图无法识别要修改的记录。需要在表单中添加主键的隐藏字段,让POST请求能携带ID信息。
修复模板代码:
在表单内添加{{ form.id }}(ModelForm默认会将主键渲染为隐藏字段):
<div class="table table-striped table-hover"> <div class="table-row"> <th style="width: 42%">Name</th> <th style="width: 43%">Token</th> <th style="width: 15%">Action</th> </div> {% for form in forms %} <div class="table-row"> <form method="POST"> {% csrf_token %} <!-- 添加隐藏的主键字段,传递记录ID --> {{ form.id }} <div class="table-cell">{{ form.name }}</div> <div class="table-cell">{{ form.token }}</div> <div class="table-cell"><button class="btn btn-lg btn-success w-100">Save</button></div> </form> </div> {% endfor %} </div>
额外注意事项
- 确保
TrafficSourcesForm继承自ModelForm,且未在fields中排除主键字段(默认会自动包含)。 - 原视图代码中
new_form = TrafficSourcesForm()和forms = [...]的缩进错误,需调整到POST判断逻辑之外,避免覆盖或重复创建。
内容的提问来源于stack exchange,提问作者mrdeath4
相关产品推荐
相关产品推荐

