Django如何实现动态行表单数据存入JSONField替代默认文本框
实现方案
第一步:修改Django表单定义
首先你需要把表单中的jsonData字段设置为隐藏控件,不要直接展示给用户填写:
from django import forms from .models import RoadConstruction class RoadConstructionForm(forms.ModelForm): class Meta: model = RoadConstruction fields = ["fromCity", "toCity", "status", "jsonData"] widgets = { # 将jsonData设置为隐藏输入框 "jsonData": forms.HiddenInput() }
第二步:修改HTML模板,添加动态表格与交互逻辑
不要直接用{{form}}渲染全部字段,拆分渲染普通字段,额外新增自定义的动态表格和JS交互逻辑:
<form action="" method="POST" id="roadForm"> {% csrf_token %} <!-- 正常渲染基础字段 --> <div style="margin: 8px 0;"> {{ form.fromCity.label_tag }} {{ form.fromCity }} {% if form.fromCity.errors %}<span style="color:red;">{{ form.fromCity.errors.0 }}</span>{% endif %} </div> <div style="margin: 8px 0;"> {{ form.toCity.label_tag }} {{ form.toCity }} {% if form.toCity.errors %}<span style="color:red;">{{ form.toCity.errors.0 }}</span>{% endif %} </div> <div style="margin: 8px 0;"> {{ form.status.label_tag }} {{ form.status }} {% if form.status.errors %}<span style="color:red;">{{ form.status.errors.0 }}</span>{% endif %} </div> <!-- 隐藏的jsonData字段,用来存储组装后的JSON字符串 --> {{ form.jsonData }} <!-- 自定义动态录入表格 --> <h4>明细数据录入</h4> <table id="dataTable" border="1" cellpadding="8" cellspacing="0" style="margin: 10px 0;"> <thead> <tr> <th>colA</th> <th>colB</th> <th>colC</th> <th>操作</th> </tr> </thead> <tbody> <!-- 默认展示一行空输入 --> <tr> <td><input type="text" class="col-input" name="colA"></td> <td><input type="text" class="col-input" name="colB"></td> <td><input type="text" class="col-input" name="colC"></td> <td><button type="button" class="delRow">删除</button></td> </tr> </tbody> </table> <button type="button" id="addRow" style="margin: 10px 0;">+ 新增行</button> <br> <input type="submit" value="Submit"> </form> <script> // 新增行逻辑 document.getElementById('addRow').addEventListener('click', function() { const tbody = document.querySelector('#dataTable tbody'); const newRow = document.createElement('tr'); newRow.innerHTML = ` <td><input type="text" class="col-input" name="colA"></td> <td><input type="text" class="col-input" name="colB"></td> <td><input type="text" class="col-input" name="colC"></td> <td><button type="button" class="delRow">删除</button></td> `; tbody.appendChild(newRow); }); // 删除行逻辑,适配动态新增的行 document.querySelector('#dataTable tbody').addEventListener('click', function(e) { if (e.target.classList.contains('delRow')) { // 限制至少保留1行数据 if (this.querySelectorAll('tr').length > 1) { e.target.closest('tr').remove(); } else { alert('至少保留一行数据'); } } }); // 表单提交前组装JSON数据 document.getElementById('roadForm').addEventListener('submit', function(e) { const rows = document.querySelectorAll('#dataTable tbody tr'); const jsonData = []; rows.forEach(row => { const colA = row.querySelector('input[name="colA"]').value.trim(); const colB = row.querySelector('input[name="colB"]').value.trim(); const colC = row.querySelector('input[name="colC"]').value.trim(); // 可自行添加空值校验、过滤逻辑 jsonData.push({ colA: colA, colB: colB, colC: colC }); }); // 将组装好的JSON数组转为字符串,写入隐藏的jsonData字段 this.querySelector('input[name="jsonData"]').value = JSON.stringify(jsonData); }); </script>
第三步:后端视图正常处理表单即可
Django的JSONField会自动把前端提交的合法JSON字符串转为对应格式存储到数据库,不需要额外做转换处理,视图示例:
from django.shortcuts import render, redirect from .forms import RoadConstructionForm def road_construction_create(request): if request.method == "POST": form = RoadConstructionForm(request.POST) if form.is_valid(): form.save() # 替换为你自己的成功跳转路由 return redirect('your_success_page') else: form = RoadConstructionForm() return render(request, 'xyz.html', {'form': form})
如果后续需要支持编辑场景,只需要在渲染模板时把已存储的jsonData转为JSON字符串传给前端,JS初始化时根据数据生成对应行数的表格即可。
内容的提问来源于stack exchange,提问作者raviujjwal
相关产品推荐
相关产品推荐

