Django for循环生成多表单时仅提交单个表单问题咨询
问题根源
- 你把全局的
<form>标签放在了for循环外侧,导致所有可预约日期的表单字段都在同一个表单内,提交时会一并上传所有重复字段,Django单表单校验要求所有字段都合法,所以必须填完所有条目才能提交 - 循环内渲染的是同一个表单实例的字段,没有和当前遍历的
StaffDuty值班对象绑定,提交后也无法关联到用户选中的对应日期 - 原
form_valid方法缺少返回值,就算提交成功也不会执行后续的保存、跳转逻辑
修复方案
1. 修改views.py
补全form_valid的返回逻辑,调整上下文变量名更语义化:
class UserAppointmentAddView(CreateView): model = UserAppointment form_class = UserAppointmentForm template_name = "reservation.html" def form_valid(self, form): form.instance.user = self.request.user.userinformation # 必须补这个返回,否则不会执行保存、跳转的默认逻辑 return super().form_valid(form) def get_context_data(self, **kwargs): # 改变量名避免和预约对象混淆,按值班日期排序更合理 kwargs['duty_list'] = StaffDuty.objects.order_by('date_work') return super().get_context_data(**kwargs)
2. 修改HTML模板
把form标签放到循环内部,每个值班条目对应独立表单,同时预填staff字段为当前值班ID,减少用户操作:
<div class="container"> {% for duty in duty_list %} <!-- 每个可预约日期对应一个独立表单,提交只会上传当前表单的内容 --> <form method="post"> {% csrf_token %} <!-- 隐藏的staff字段,预填当前遍历的值班ID,用户不需要手动选择 --> <input type="hidden" name="staff" value="{{ duty.id }}"> <span>可预约日期:{{ duty.date_work }}</span> <span>{{ form.event }}</span> <span>{{ form.morning_hour }}</span> <span>{{ form.afternoon_hour }}</span> <div class="primary-btn"> <input type="submit" value="预约该日期" class="btn btn-primary"> </div> </form> {% endfor %} </div>
3. 可选优化
如果你的UserAppointmentForm里staff是必填字段,上述写法已经通过隐藏字段提交了对应值,无需修改表单配置;如果需要根据值班日期过滤可选的活动、时段,可以在视图的get_form方法中根据请求参数动态调整表单选项。
内容的提问来源于stack exchange,提问作者PeroPuri
相关产品推荐
相关产品推荐

