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

Django UpdateView处理主表单与inline_formset时form_valid不触发问题

问题根因

你遇到的核心问题是错误重写了get_form方法:
Django的UpdateView默认get_form方法会自动将request.POST/request.FILES中的提交数据绑定到表单实例,再做校验。但你重写的get_form仅传入了instance参数,没有绑定任何提交数据,导致父类post方法执行校验时,拿到的是无数据绑定的空表单,自然校验失败触发form_invalid;又因为表单没有绑定提交数据,所以form.errors为空没有错误输出。
你在post方法中自己实例化的regular_form因为绑定了request.POST所以校验可以通过,这也印证了上面的根因。


其他待修正的问题

  1. 逻辑顺序错误:你提前在post方法中保存了formset,如果后续主表单校验失败,会导致关联数据提前写入数据库产生脏数据
  2. 模板冗余:HTML模板中多写了一行{{ formset.management_form }},你实际使用的formset变量名是response_formset,这行多余代码可能会引发前端警告

解决方案

不需要更换CBV,UpdateView完全可以满足需求,按以下步骤修改代码即可:

1. 修正视图逻辑

删除错误的get_form方法,调整post和form_valid逻辑,保证主表单和formset都校验通过后再统一保存:

class GrowthPlanUpdateView(
    LoginRequiredMixin, UserIsObserverOrObserveeMixin, UpdateView
):
    model = GrowthPlan
    template_name = "commonground/growthplan_form.html"
    form_class = GrowthPlanForm
    pk_url_kwarg = "growthplan_id"

    def get_object(self):
        return get_object_or_404(GrowthPlan, pk=self.kwargs["growthplan_id"])

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form()
        # 实例化formset并绑定提交数据
        self.response_formset = ResponseInlineFormset(
            request.POST or None,
            prefix="response_formset",
            instance=self.object,
        )
        # 主表单和formset都校验通过才进入成功逻辑
        if form.is_valid() and self.response_formset.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        # 先保存主对象
        self.object = form.save()
        # 再保存关联formset数据
        self.response_formset.save()
        messages.add_message(
            self.request, messages.SUCCESS, "Changes were saved!"
        )
        return super().form_valid(form)

    def form_invalid(self, form):
        # 调试时可以同时打印主表单和formset的错误,方便定位问题
        print("主表单错误:", form.errors)
        print("formset错误:", self.response_formset.errors)
        return super().form_invalid(form)

    # get_success_url、get_context_data方法保持原有逻辑不变即可

2. 修正模板代码

删除HTML中多余的management_form声明,修改后表单部分代码如下:

<form method="post" novalidate>
    {% csrf_token %}
    {{ form.as_p }}
    {{ response_formset.management_form }}
    {% for formset_form in response_formset.forms %} 
        {{ formset_form.as_p }}
    {% endfor %}
    <button type="submit" class="btn btn-primary"><i class="fal fa-clipboard-check"></i> Update Growth Plan</button>
</form>

内容的提问来源于stack exchange,提问作者Hanny

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:06:03