Django动态表单多IP端口提交失败:索引未更新问题求助
Hey there! Let's fix that formset index issue you're facing with your Django dynamic IP/port form. I've gone through your code and spotted a few key problems that are causing the submission to fail when adding multiple entries:
1. Fix the Form Widget Class Typo
In your formulario_members form, you have a critical typo in the Meta class: you wrote widget (singular) instead of widgets (plural). This means your CSS class settings weren't being applied at all, so your JavaScript couldn't find the fields to update their indices.
Update your form like this:
class formulario_members(ModelForm): class Meta: model=members fields= ["nodo", "port",] widgets = { # Changed from "widget" to "widgets" "nodo":forms.TextInput(attrs={"class":"F5APP-field formset-field"}), "port":forms.TextInput(attrs={"class":"F5APP-field formset-field"}), }
Adding the formset-field class here lets your JavaScript target these fields correctly for index updates.
2. Fix the JavaScript Index Update Logic
Your core index update logic was close, but there were gaps in how fields were targeted and reindexed after add/delete actions. Here's the revised code:
Update the updateElementIndex function
This ensures we correctly match and replace the form indices in all relevant attributes:
function updateElementIndex(el, prefix, ndx) { var idRegex = new RegExp(`(${prefix}-\\d+-)`); var replacement = `${prefix}-${ndx}-`; // Update label's "for" attribute if present if ($(el).attr("for")) { $(el).attr("for", $(el).attr("for").replace(idRegex, replacement)); } // Update element's id and name attributes if (el.id) el.id = el.id.replace(idRegex, replacement); if (el.name) el.name = el.name.replace(idRegex, replacement); }
Fix the addForm function
This ensures cloned rows get fresh values and correctly updated indices:
function addForm(btn, prefix) { var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val()); if (formCount < 1000) { // Clone the last form row without copying events var row = $(".item:last").clone(false).get(0); $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300); // Clear error messages and reset field states $(".errorlist", row).remove(); $(row).find('.formset-field').removeClass("error"); // Update indices and reset field values $(row).find('.formset-field').each(function () { updateElementIndex(this, prefix, formCount); // Clear text input values if ($(this).is('input[type="text"]')) { $(this).val(''); } }); // Update total form count in management form $("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1); } return false; }
Fix the deleteForm function
This properly reindexes all remaining forms after deleting a row:
function deleteForm(btn, prefix) { var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val()); if (formCount > 1) { // Remove the selected row $(btn).parents('.item').remove(); // Get all remaining form rows var forms = $('.item'); // Update total form count $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length); // Reindex all remaining forms starting from 0 forms.each(function(index) { $(this).find('.formset-field').each(function () { updateElementIndex(this, prefix, index); }); }); } return false; }
I simplified the delete logic since you're working with unsaved new entries (no need for AJAX here unless you're handling existing saved rows).
3. Verify Template Setup
You already have {{ formset.management_form }} in your template, which is essential—Django uses this to track form counts and indices. Double-check that it's placed inside the <form> tag (which it is in your code).
Why This Works
- The widget typo fix ensures your JS can actually target the form fields to update their indices.
- The revised JS functions correctly reindex all form fields when adding or deleting rows, so Django receives properly numbered form data (e.g.,
members-0-nodo,members-1-nodo) instead of duplicate or out-of-order indices. - Clearing field values on cloned rows prevents carrying over previous entries to new rows.
After making these changes, your formset should handle multiple IP/port entries correctly, and submitting the form will save all entries without issues.
内容的提问来源于stack exchange,提问作者Jorge Roa

