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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:30:04