基于唯一ID批量保存spe_form表单的技术实现求助
批量保存多个spe_form表单的解决方案
问题背景
现有代码仅支持保存单个spe_form表单,需要实现点击保存按钮时,通过gen_form的唯一ID批量保存多个spe_form表单。
后端代码修改(使用Django FormSet)
借助Django的formset_factory处理多表单批量提交,替换原单个表单逻辑:
from django.forms import formset_factory def preps(request, prep=None): # 修正原参数判断逻辑 if prep: info = Mprep.objects.get(id=prep) else: info = Mprep() # 创建表单集,默认显示1个空表单 MSFormSet = formset_factory(MSForm, extra=1) if request.method == 'POST': gen_form = MGForm(request.POST, instance=info) # 实例化表单集,传入POST数据与前缀 form_set = MSFormSet(request.POST, prefix='preps') if gen_form.is_valid() and form_set.is_valid(): # 保存主表单并获取实例 saved_gen = gen_form.save() # 遍历表单集,批量保存子表单 for form in form_set: if form.cleaned_data: # 跳过空表单 spe_instance = form.save(commit=False) spe_instance.prep = saved_gen spe_instance.save() messages.success(request, '信息保存成功') return redirect('preps_view', prep=saved_gen.id) else: messages.error(request, '保存信息出错') else: gen_form = MGForm(instance=info) form_set = MSFormSet(prefix='preps') context = {'gen_form': gen_form, 'spe_form_set': form_set} return render(request, 'base.html', context)
前端模板调整
修改HTML模板,正确渲染表单集并保留添加行功能:
<div class="container mt-5"> <h1>Measurements Prep</h1> <form method="post"> {% csrf_token %} <div class="form-row"> <div class="form-group col-4"> {{ gen_form.project|as_crispy_field }} </div> <div class="form-group col-4"> {{ gen_form.cell|as_crispy_field }} </div> <div class="form-group col-4"> {{ gen_form.sample|as_crispy_field }} </div> </div> <br> <!-- 必须渲染表单集管理组件,用于Django识别表单数量 --> {{ spe_form_set.management_form }} <table id="myTable" class="table" data-toggle="table" data-mobile-responsive="true" data-pagination="true" data-height="460"> <thead> <tr> <th>名称</th> <th>数值</th> <th>单位</th> </tr> </thead> <tbody> <!-- 遍历渲染表单集中的所有表单 --> {% for form in spe_form_set %} <tr class="form-row"> <td>{{ form.name|as_crispy_field }}</td> <td>{{ form.value|as_crispy_field }}</td> <td>{{ form.unit|as_crispy_field }}</td> </tr> {% endfor %} </tbody> </table> <button id="add-row-button" class="btn btn-primary mt-4">添加行</button> <input type="submit" class="btn btn-primary mt-4" value="保存"> </form> </div>
JavaScript动态添加行逻辑调整
动态生成符合Django表单集格式的新行,更新表单计数:
document.getElementById("add-row-button").addEventListener("click", function () { // 获取表单集总数量控件 var totalForms = document.getElementById('id_preps-TOTAL_FORMS'); var formCount = parseInt(totalForms.value); var tableBody = document.querySelector("#myTable tbody"); var newRow = document.createElement("tr"); newRow.className = "form-row"; // 替换空表单中的占位符__prefix__为当前表单索引 newRow.innerHTML = ` <td>${"{{ spe_form_set.empty_form.name|as_crispy_field }}".replace(/__prefix__/g, formCount)}</td> <td>${"{{ spe_form_set.empty_form.value|as_crispy_field }}".replace(/__prefix__/g, formCount)}</td> <td>${"{{ spe_form_set.empty_form.unit|as_crispy_field }}".replace(/__prefix__/g, formCount)}</td> `; tableBody.appendChild(newRow); // 更新表单集总数量 totalForms.value = formCount + 1; });
关键注意事项
- 必须渲染
{{ spe_form_set.management_form }},Django依赖它跟踪表单集中的表单数量与索引 - 动态添加表单时,需将
empty_form中的__prefix__替换为当前表单计数,确保字段name格式为preps-<index>-name,符合Django表单集识别规则 - 保存时过滤空表单,避免创建无数据的数据库实例
内容的提问来源于stack exchange,提问作者Munther Odeh
相关产品推荐
相关产品推荐

