Clone formset data not saved.

Im having the trouble of saving a cloned formset data right now. Now it just saved whatever its at the last row. The cloning works well as shown in the pic. Everything is working well for my web except for this part. To all the pros out there, im a beginner in this, please help me. Would really appreciate it. Stuck at this for 4 days already. If i do a print(di_form.errors) under di_form.is_valid(), i get the following error [{}, {}, {}]. If iprint(di_form.non_form_errors) , <bound method BaseFormSet.non_form_errors of <django.forms.formsets.DeviceInterfaceFormFormSet object at 0x00000198CCC56B80>> appears on powershell

Assuming all the fields are with text. Those in red circle are not saved and the one in blue circle is saved upon clicking save

Here is my code:

views.py

def device_add(request):
    if request.method == "POST":
        device_frm = DeviceForm(request.POST) ##Part A1
        dd_form = DeviceDetailForm(request.POST)
        #di_form= DeviceInterfaceForm(request.POST)
        di_formset = modelformset_factory(DeviceInterface, fields=('moduletype', 'firstportid', 'lastportid'), extra=1,max_num=3)
        di_form=di_formset(request.POST)
        if device_frm.is_valid():
        # Create and save the device
        # new_device here is the newly created Device object
            new_device = device_frm.save()
            if dd_form.is_valid():
                # Create an unsaved instance of device detail
                deviceD = dd_form.save(commit=False)
                # Set the device we just created above as this device detail's device
                deviceD.DD2DKEY = new_device
                # If you did not render the hostname for the device detail, set it from the value of new device
                deviceD.hostname = new_device.hostname
                deviceD.save()
                if di_form.is_valid():
                    
                    deviceI=di_form.save(commit=False) 
                for instances in deviceI:          ##Newly added
                    instances.I2DKEY=new_device    ##Newly added
                    instances.save()               ##Newly Added
                
                print(di_form.non_form_errors)  ##This print line gives me <bound method BaseFormSet.non_form_errors of <django.forms.formsets.DeviceInterfaceFormFormSet object at 0x00000198CCC56B80>>
                    #for deviceI in deviceI:          
                     #   deviceI.I2DKEY=new_device
                    #   deviceI.save()

                    print(deviceI)
                    return render(request, 'interface/device_added.html',{'devices':Device.objects.all()})
                else:
                    print(di_form.non_form_errors())
                return render(request,'interface/device_add.html',{'form':device_frm, 'dd_form': dd_form, 'di_form':di_form})
            return render(request,'interface/device_add.html',{'form':device_frm, 'dd_form': dd_form, 'di_form':di_form})
        return render(request,'interface/device_add.html',{'form':device_frm, 'dd_form': dd_form, 'di_form':di_form})
    else:
        device_frm = DeviceForm()
        dd_form = DeviceDetailForm()
        di_formset = modelformset_factory(DeviceInterface, fields=('moduletype', 'firstportid', 'lastportid'),extra=1, max_num=3)
        di_form=di_formset(queryset = DeviceInterface.objects.none())
        return render(request,'interface/device_add.html',{'form':device_frm, 'dd_form': dd_form, 'di_form':di_form})

device_add.html

<script>
let maxrow = $('#id_form-MAX_NUM_FORMS').attr('value');
 $('#addrow').click(function () {
        let formregex = RegExp(`form-(\\d){1}-`,'g');
        let formnumber = $('#morerows #rowAddition').length+1;
        console.log(formnumber);
        console.log(maxrow +" max");
   
        $('#id_form-TOTAL_FORMS').attr("value",formnumber);
        let wholerowclone = $('#rowAddition').clone();
        wholerowclone.replaceWith(formregex, `form-${formnumber}-`)
        let wholerowcloneblank = wholerowclone.find('input').val('').end();
        let wholerow = wholerowcloneblank.appendTo('#morerows');
      
        $('#morerows').append(wholerow);

        
        
        if(formnumber == maxrow) {

            $('#addrow').attr("disabled", true)
            $('#addrow').attr("class","btn btn-rounded btn-danger")
            $('#addrow i').attr("class","")
            $('#addrow').html("Reached max limit")
        }
        $('#morerows #rowAddition #removerow').css('display','block');
       
    });

    $(document).on('click', '#removerow', function () {
        let formnumber = $('#morerows #rowAddition').length-1;
        $(this).closest('#rowAddition').remove();
        if(formnumber<maxrow){
            
            $('#addrow').attr("disabled", false)
            $('#addrow').attr("class","btn btn-outline-success btn-rounded")
            $('#addrow i').attr("class","dripicons-plus")
            $('#addrow').html("+") 
        }  
          
    });
</script>

<span>Module form:</span>



                            <button type="button" class="btn btn-outline-success btn-rounded" id="addrow"><i
                                    class="dripicons-plus"></i></button>

                                   <br><br>
                            {{di_form.management_form}}
                            {% for form in di_form %}
                            <div id="rowAddition">
                                <div class="row">
                                    <div class="col-md-2">
                                        <div class="form-group">
                                            <label for="{{dd_form.moduletype.id_for_label}}">Module Type<span
                                                class="text-danger">*</span></label>
                                                {{form.moduletype}}
                                            
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="form-group">
                                            <label for="{{di_form.firstportid.id_for_label}}">First Port ID<span
                                                class="text-danger">*</span></label>
                                            {{form.firstportid}}
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="form-group">
                                            <label for="{{di_form.lastportid.id_for_label}}">Last Port ID <span
                                                class="text-danger">*</span></label>
                                            {{form.lastportid}}
                                        </div>
                                    </div>  
                                    <div class="col-md-1">
                                        <div class="form-group">
                                            <div class="text-sm-center">
                                                <br />
                                                <button type="button" class="btn btn-outline-danger btn-rounded"
                                                    id="removerow" style="display: none"><i class="dripicons-minus"></i></button>
                                            </div>
                                        </div>
                                    </div>                            
                            {%endfor%}
                            

                                </div>
                            </div>
                        
                            <!--more rows-->
                            <div id='morerows'>
                            </div>
                     

                            <!--more rows-->

Error from development tools

jquery.js:4055 Uncaught TypeError: Cannot set property '_DT_CellIndex' of undefined
    at Ja (jquery.dataTables.min.js:24)
    at O (jquery.dataTables.min.js:16)
    at HTMLTableRowElement.<anonymous> (jquery.dataTables.min.js:17)
    at jquery.js:208
    at Function.map (jquery.js:463)
    at R.fn.init.map (jquery.js:207)
    at oa (jquery.dataTables.min.js:17)
    at e (jquery.dataTables.min.js:93)
    at HTMLTableElement.<anonymous> (jquery.dataTables.min.js:93)
    at Function.each (jquery.js:381)

Couple quick comments

First, when I see formsets acting like that, it’s typically because something in the construction of the form (the repeated fields) isn’t right. You can check that by looking at your rendered page in your browsers developer tools to ensure your form is structured as it’s supposed to be.

Then, you can look at what’s being submitted in the network tab of those tools. That’ll tell you whether you’re getting 4 entries submitted or just one.

non_form_errors is a function, not an attribute - you want to call it as non_form_errors()

Finally, I see where you’re recreating multiple forms (and formsets) from the same request.POST. When you’re doing that, I always recommend using a prefix on each form to ensure isolation between the submitted data.

Sorry for the late reply, I realise its a function and but it still return me the same error, <bound method BaseFormSet.non_form_errors of <django.forms.formsets.DeviceInterfaceFormFormSet object at 0x000001646D9EDB20>>. For the forms, it is counting correctly under the development tools -console

I’m sorry, I’ve lost track of what you’re reporting here.

What specific line of code is doing this? (By the way, this is a real side-bar issue, and not in any direct way related to the original problem reported. I would not consider this a critical item at this point.)

What is counting correctly?

I hadn’t asked for you to check out your JavaScript, I suggested you check the HTML being rendered to ensure it is correct. Also, I suggested you verify your form submission in the network tab.

Hi, I managed to save the clone formset. But i am currently having a issue where the ‘-’ button (purpose:remove clone) not working properly. Now it just remove everything. Is it possible for u to advise what i am doing wrong? Here’s my code:

                           {{di_form.management_form}}

                            <div id = "rowAddition">
                            {% for form in di_form %}
                            <div>
                                <div class="row">
                                    <div class="col-md-2">
                                        <div class="form-group">
                                            <label for="{{dd_form.moduletype.id_for_label}}">Module Type<span
                                                class="text-danger">*</span></label>
                                                {{form.moduletype}}               
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="form-group">
                                            <label for="{{di_form.firstportid.id_for_label}}">First Port ID<span
                                                class="text-danger">*</span></label>
                                            {{form.firstportid}}
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="form-group">
                                            <label for="{{di_form.lastportid.id_for_label}}">Last Port ID <span
                                                class="text-danger">*</span></label>
                                            {{form.lastportid}}
                                        </div>
                                    </div>  
                                </div>
                            </div>
                            {%endfor%}

                            <div id="empty-form" style="display: none;">
                                <div>
                                {{di_form.empty_form}}
                                    <div class="col-md-1">
                                        <div class="form-group">
                                            <div class="text-sm-center">
                                                <br />
                                                <button type="button" class="btn btn-outline-danger btn-rounded"
                                                    id="removerow" style="display: none;"><i class="dripicons-minus"></i></button>
                                            </div>
                                        </div>
                                    </div>
                                </div> 
                                <hr><br><br>
                            </div>
                        </div>
                        
                        
                            <!--more rows-->
                            <div id='morerows'>
                            </div>

This my script :

let changeFlag=0;
    let maxrow = $('#id_form-MAX_NUM_FORMS').attr('value');
    let totalForms = $('#id_form-TOTAL_FORMS').val();
    

    $('#deleteConfirmation').modal('hide');

    function portidChange(val) {
        changeFlag = 1;
        if (val =="")
        changeFlag = 0;
    }


    $('#addrow').click(function () {
        

        
        let totalForms = $('#id_form-TOTAL_FORMS').val();
        $('#empty-form #removerow').css('display','block');   
        let wholerowclone = $('#empty-form').clone();
        $('#morerows').append(wholerowclone.html().replace(/__prefix__/g, totalForms));
        $('#id_form-TOTAL_FORMS').attr('value', (parseInt (totalForms))+1);
  
        changeFlag=0;

        
        if(totalForms==maxrow) {
            
            $('#addrow').attr("disabled", true);
            $('#addrow').attr("class","btn btn-rounded btn-danger");
            $('#addrow i').attr("class","");
            $('#addrow').html("Reached max limit");
        }

        
    })


   
    

    $(document).on('click', '#removerow', function () {
        let totalForms = $('#id_form-TOTAL_FORMS').val();
        console.log(this.closest('#morerows'));
        $(this).closest('#morerows').remove();
        if(totalForms<maxrow){
            
            $('#addrow').attr("disabled", false)
            $('#addrow').attr("class","btn btn-outline-success btn-rounded")
            $('#addrow i').attr("class","dripicons-plus")
            $('#addrow').html("+") 
        }  
          
    });
    $('input').attr('class', 'form-control'); //Making the textbox look nicer
    $('select').attr('class', 'custom-select mb-3'); //Making the select box(drop box) look nicer

Always remember that the id attribute in html elements must be unique in a page. It is always wrong to have two or more elements on a page with the same id.

Sorry about that. I replace that already