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

使用jQuery克隆的表单行无法通过POST方法提交至后端

Django克隆表单行无法提交POST数据问题

在Django项目中实现添加新输入行的功能,通过jQuery克隆已有行生成新行,新行可正常显示,但克隆出的新行数据无法通过POST提交到后端。

JavaScript代码

function addRow_editProduct(currentRowCount, productPK) {
 
    var rowCounter = currentRowCount + 1;
 
    var container = document.getElementById(productPK + '_productMaterialContainer');
 
    var templateRow = $('#' + productPK + '_productMaterial_row' + currentRowCount);
    var newRow = templateRow.clone();
    
    newRow.attr('id', productPK + '_productMaterial_row' + rowCounter);
    newRow.find('[id^="' + productPK + '_product_material"]').attr('id', productPK + '_product_material' + rowCounter).attr('name', productPK + '_product_material' + rowCounter);
    newRow.find('[id^="quantity"]').attr('id', 'quantity' + rowCounter).attr('name', 'quantity' + rowCounter);
    newRow.find('[id^="unit"]').attr('id', 'unit' + rowCounter).attr('name', 'unit' + rowCounter);
    newRow.find('[id^="' + productPK + '_productMaterial_pk"]').val('');
 
    newRow.find('select').val('delete'); 
    newRow.find('input[name^="quantity"]').val('');  
    newRow.find('input[name^="unit"]').val('');  
 
    newRow.find('.delete-productMaterial').attr('data-select-element-id', productPK + '_product_material' + rowCounter);
 
    $(container).append(newRow);
 
    console.log('document', $('#' + productPK + '_productMaterial_row' + rowCounter).find('[id^="' + productPK + '_product_material"]').attr('name'));
 
    
    // var formData = new FormData($('#test')[0]);
    // for (var pair of formData.entries()) {
    //     console.log(pair[0] + ': ' + pair[1]);
    // }
       
}

HTML代码

<div id="{{product_data.product.pk}}_productMaterialContainer">
    {% for y in product_data.materials %}
    <div class="row align-items-center mt-2" id="{{product_data.product.pk}}_productMaterial_row{{ forloop.counter }}">
        <input type="hidden" name="{{product_data.product.pk}}_productMaterial_pk{{ forloop.counter }}" id="{{product_data.product.pk}}_productMaterial_pk{{ forloop.counter }}" value="{{ y.pk }}">
        <div class="col-4">
            <select class="input-select" id="{{product_data.product.pk}}_product_material{{ forloop.counter }}" name="{{product_data.product.pk}}_product_material{{ forloop.counter }}" value="{{y.material.pk}}">
                <option value="delete">None</option>
                {% for z in materials %}
                    <option value="{{z.pk}}" {% if z.pk == y.material.pk %}selected{% endif %}>{{z.name}}</option>
                {% endfor %}
            </select>
        </div>
        <div class="col-3">
            <input type="number" class="form-control" id="quantity{{ forloop.counter }}" name="quantity{{ forloop.counter }}" value="{{y.quantity}}">
        </div>
        <div class="col-3">
            <input type="text" class="form-control" id="unit{{ forloop.counter }}" name="unit{{ forloop.counter }}" value="{{y.material.unit}}" readonly>
        </div> 
        <div class="col-1">
            <button type="button" class="btn dark-button delete-productMaterial" data-select-element-id="{{product_data.product.pk}}_product_material{{ forloop.counter }}" data-row-id="{{product_data.product.pk}}_productMaterial_row{{ forloop.counter }}"> &times </button>
        </div>
    </div>
    {% endfor %}
</div>
<button type="button" class="btn dark-button mt-4 addRowEditProduct" data-product-pk="{{product_data.product.pk}}">Add Row</button>

后端Python代码(仅作参考)

if(request.method=="POST"):
        stock = request.POST.get("stock")
        name = request.POST.get("name")
 
        print(request.POST)
 
        
        if 'edit_form' in request.POST:
            product_pk = request.POST.get("product_pk")
            product = get_object_or_404(Product, pk=product_pk)
            x=1
 
            while True:
                pm_pk = request.POST.get(f"{product_pk}_productMaterial_pk{x}")
                quantity = request.POST.get(f"quantity{x}")
                materialID = request.POST.get(f"{product_pk}_product_material{x}")
 
                if materialID is None:
                    break
                else:
                    if pm_pk: 
                        if materialID == "delete":
                            Product_Material.objects.filter(pk=pm_pk).delete()
                        else:
                            Product_Material.objects.filter(pk=pm_pk).update(material=materialID, quantity=quantity)
                    else:
                        if materialID != "delete":
                            material_object = get_object_or_404(Material, pk=materialID)
                            Product_Material.objects.create(product=product, material=material_object, quantity=quantity)
                x+=1
            Product.objects.filter(pk=product_pk).update(stock=stock, name=name)
            return redirect('products')

排查信息

  • 控制台日志确认新行的name属性已正确更新:
document 39_product_material3
products:1128 document 39_product_material4
products:1128 document 39_product_material5
  • 后端打印request.POST时,无克隆行的输入数据:
<QueryDict: {'csrfmiddlewaretoken': ['2KJ70EwX6mog6lTkfQH7d9ykkBcBLXbFIbKFfRBwJzGMDGEfKQSas9R5WJ2KbyPQ'], 'edit_form': ['1'], 'product_pk': ['39'], 'name': ['123'], '39_productMaterial_pk1': ['49'], '39_product_material1': ['49'], 'quantity1': ['1'], 'unit1': ['per inch'], '39_productMaterial_pk2': ['51'], '39_product_material2': ['50'], 'quantity2': ['2'], 'unit2': ['per inch'], 'stock': ['112'], 'cost': ['']}>

求助需求

不清楚克隆行数据无法提交的原因,求排查建议或可实现相同功能的代码重构方案。

内容的提问来源于stack exchange,提问作者Duncan Ling

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:30:54