Django表单POST提交未保存问题求助:日程表功能开发遇阻
问题分析与解决方案
兄弟,我帮你排查了下代码,点击保存后旧值恢复的问题主要出在前端没正确提交修改数据和后端处理后没加载最新数据这两个关键点上,具体来说:
核心问题拆解
前端表单控件未绑定Django表单字段
你现在是手动写了<select>和<input>,但这些控件没有设置name属性——Django的表单集需要通过name(比如form-0-value这种格式)来识别每个字段对应的数据,所以你修改后的值根本没传到后端。而且初始状态下控件是disabled/readonly,就算解除了限制,没有name浏览器也不会把值发给服务器。后端POST处理后未刷新表单集
你在POST分支里保存了表单,但之后还是返回最初用旧数据生成的timetableform,所以页面刷新后显示的还是修改前的内容,没有加载数据库里的最新值。
具体修改步骤
1. 修正views.py的逻辑
保存表单后要重新生成表单集,确保返回的是最新数据:
@login_required(login_url='login') def timetable(request): # 类名建议用大驼峰,符合Python规范 TimeTableFormset = modelformset_factory(timeTable, fields='__all__' ,extra=0) if request.method == 'POST': formset = TimeTableFormset(request.POST) if formset.is_valid(): formset.save() # 保存后重新获取最新的表单集 formset = TimeTableFormset(queryset=timeTable.objects.all()) else: # GET请求时初始化表单集 formset = TimeTableFormset(queryset=timeTable.objects.all()) return render(request, 'VulnManager/timetable.html', {'timetableform': formset})
2. 重构timetable.html的表单渲染
用Django表单自带的字段渲染,确保name属性正确,同时保留你的表格布局:
<form method="POST"> {% csrf_token %} {{ timetableform.management_form }} <table id="tablePreview" class="table table-borderless table-hover"> <thead> <tr> <th></th> <th>Monday</th> <th>Tuesday</th> <th>Wednesday</th> <th>Thursday</th> <th>Friday</th> <th>Saturday</th> <th>Sunday</th> </tr> </thead> <tbody> <tr> <th scope="row">Scan?</th> {% for form in timetableform.forms %} <!-- 表单集必须的隐藏字段,用来识别对应数据库实例 --> {{ form.id }} {{ form.key.as_hidden }} {% if forloop.counter <= 7 %} <td> <select class="form-control scan-select" name="{{ form.value.name }}" disabled> <option value="true" {% if form.value.value == "true" %}selected{% endif %}>true</option> <option value="false" {% if form.value.value == "false" %}selected{% endif %}>false</option> </select> </td> {% if forloop.counter == 7 %} </tr> <tr> <th scope="row">Time begin</th> {% endif %} {% elif forloop.counter >= 8 and forloop.counter <= 14 %} <td> <input type="text" class="form-control time-input" name="{{ form.value.name }}" value="{{ form.value.value }}" onchange="validateHhMm(this);" disabled /> </td> {% if forloop.counter == 14 %} </tr> <tr> <th scope="row">Time end</th> {% endif %} {% elif forloop.counter >= 15 and forloop.counter <= 21 %} <td> <input type="text" class="form-control time-input" name="{{ form.value.name }}" value="{{ form.value.value }}" onchange="validateHhMm(this);" disabled /> </td> {% endif %} {% endfor %} </tr> </tbody> </table> <input type="button" class="btn-primary" id="edit" value="Edit" /> <input type="submit" class="btn-primary" id="save" value="Save" /> </form> <script> // 编辑按钮切换控件的可编辑状态 document.getElementById('edit').addEventListener('click', function() { const selects = document.querySelectorAll('.scan-select'); const inputs = document.querySelectorAll('.time-input'); selects.forEach(select => select.disabled = !select.disabled); inputs.forEach(input => input.disabled = !input.disabled); }); </script>
关键修改说明
- 加入了
{{ form.id }}和{{ form.key.as_hidden }}:这是Django表单集识别每个模型实例的必须字段,不能少。 - 所有控件都添加了
name="{{ form.value.name }}":确保修改后的数据能正确提交到后端,匹配表单集的字段。 - 用
disabled替代readonly:结合JS实现编辑/只读切换,disabled的控件默认不会提交,开启后才会发送值。 - 后端保存后重新生成表单集:保证页面刷新后显示的是最新的数据库数据。
最后提醒下:要确保数据库里已经存在21条记录(7天 × 3个配置项:Scan?、Time begin、Time end),因为你的formset设置了extra=0,不会自动添加新记录哦~
内容的提问来源于stack exchange,提问作者Marvin
相关产品推荐
相关产品推荐

