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所以校验可以通过,这也印证了上面的根因。
其他待修正的问题
- 逻辑顺序错误:你提前在
post方法中保存了formset,如果后续主表单校验失败,会导致关联数据提前写入数据库产生脏数据 - 模板冗余: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
相关产品推荐
相关产品推荐

