如何对动态生成的Django表单做验证并实现批量提交处理
实现方案
前端配置
- 每一行的表单字段需要添加带有序号的标识,推荐直接使用Django自带的表单集(FormSet)约定的命名规则:第N行的字段名格式为
expense-N-字段名,比如第0行的项目字段叫expense-0-project、金额字段叫expense-0-amount。 - 表单内新增两个隐藏字段:
expense-TOTAL_FORMS(值为当前页面总共有多少行开销表单)、expense-INITIAL_FORMS(新增场景下默认值为0即可)。 - 动态新增行时,只要把新行的字段序号按已有最大序号+1设置,同时更新
expense-TOTAL_FORMS的value为最新行数即可。
后端视图实现
直接用Django内置的formset_factory构造批量表单,示例代码如下:
from django.forms import formset_factory def bulk_new_expense(request): data = { 'title': "批量新增开销", } # 原有上下文参数保持不变 data['projects'] = Project.objects.filter(is_visible=True).values('id') data['expense_category'] = dict((y, x) for x, y in EXPENSE_CATEGORY) data['expense_type'] = dict((y, x) for x, y in EXPENSE_TYPE) # 构造开销表单集,extra为页面初始默认展示的空表单行数 ExpenseFormSet = formset_factory(ExpenseForm, extra=3, can_delete=False) if request.method == "POST": formset = ExpenseFormSet(request.POST) if formset.is_valid(): # 遍历每个行表单,单独处理每一行数据 for form in formset: # 可选:跳过用户未填写的空行 if form.cleaned_data: form.save() # 保存成功后重置表单集 formset = ExpenseFormSet() else: formset = ExpenseFormSet() data['formset'] = formset return render(request, "expense/bulk_new_expense.html", data)
模板渲染注意事项
直接遍历formset中的每个form对应渲染一行即可,Django会自动生成符合命名规则的字段,以及TOTAL_FORMS、INITIAL_FORMS两个必填隐藏字段,无需手动编写。
如果不想使用Django表单集,也可以自定义每一行的字段前缀(比如row0_xxx、row1_xxx),后端遍历request.POST的键名按前缀分组后,逐个传入ExpenseForm校验保存即可。表单集是官方推荐的标准化方案,能自动处理序号、校验、空行过滤等逻辑,开发效率更高。
内容的提问来源于stack exchange,提问作者Cheknov
相关产品推荐
相关产品推荐

