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

如何对动态生成的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:57:04