Django Formset中动态添加的字段为空

时间:2015-03-25 10:08:50

标签: javascript django forms

我成功地设法创建了一个表单,可以将新行添加到由两个表单集组成的表单中。

出现新字段,我可以输入并提交数据。但是在第一次提交后,这些字段显示为empthy。如果我重新输入数据,则值将正确传递。所以我在add - 脚本的末尾添加了一个重新验证,并且表单通过了。但是没有数据被添加到模型中,所以我认为数据是在第一个approche中没有传递的。

感谢您的帮助!

观点:

def pruefplan(request):

    class RequiredFormSet(BaseFormSet):
        def __init__(self, *args, **kwargs):
            super(RequiredFormSet, self).__init__(*args, **kwargs)
            for form in self.forms:
                form.empty_permitted = False

    PruefschrittAttributivFormset = formset_factory(
                                            PruefschrittAttributivForm,
                                            max_num=10,
                                            formset=RequiredFormSet,
                                            )

    PruefschrittVariabelFormset = formset_factory(
                                              PruefschrittVariabelForm,
                                              max_num=10,
                                              formset=RequiredFormSet,
                                              )

    if request.method == 'POST': # If the form has been submitted...
        # A form bound to the POST data
        pruefplan_form = PruefplanForm(request.POST) 
        # Create a formset from the submitted data
        pruefschritt_attributiv_formset = PruefschrittAttributivFormset(
                                                          request.POST,
                                                          request.FILES,
                                                          prefix='attr',
                                                          )

        pruefschritt_variable_formset = PruefschrittVariabelFormset(
                                                          request.POST,
                                                          request.FILES,
                                                          prefix='var',
                                                          )

        if (
            pruefplan_form.is_valid()
            and 
            pruefschritt_attributiv_formset.is_valid()
            and
            pruefschritt_variable_formset.is_valid()
            ):

            pruefplan = pruefplan_form.save()
            for form in pruefschritt_attributiv_formset.forms:
                attributiv_item = form.save(commit=False)
                attributiv_item.pruefplan = pruefplan
                attributiv_item.save()
            for form in pruefschritt_variable_formset.forms:
                variable_item = form.save(commit=False)
                variable_item.pruefplan = pruefplan
                variable_item.save()
            return HttpResponseRedirect('') # Redirect to a 'success' page
    else:
        pruefplan_form = PruefplanForm()
        pruefschritt_attributiv_formset = PruefschrittAttributivFormset(
                                                          prefix='attr')
        pruefschritt_variable_formset = PruefschrittVariabelFormset(
                                                           prefix='var')

    # For CSRF protection
    # See http://docs.djangoproject.com/en/dev/ref/contrib/csrf/ 

    pruefplan = Pruefplan.objects.all()

    c = {'pruefplan': pruefplan,
         'pruefplan_form': pruefplan_form,
         'pruefplan_attributiv_formset': pruefschritt_attributiv_formset,
         'pruefplan_variable_formset': pruefschritt_variable_formset,
        }
    c.update(csrf(request))


    return render_to_response('qpruefung/pruefplan.html', c)

模板:

    <div class="tab-pane fade" id="erfassung">
        <link rel="stylesheet" href="{% static 'css/jquery-ui.css' %}">
        <script src="{% static 'js/jquery-ui.js' %}"></script>

        <div class=container style="width: 80%">

<script>
$(document).ready(function () {
    // Code adapted from http://djangosnippets.org/snippets/1389/  
    function updateElementIndex(el, prefix, ndx) {
        var id_regex = new RegExp('(' + prefix + '-\\d+-)');
        var replacement = prefix + '-' + ndx + '-';
        if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex,
        replacement));
        if (el.id) el.id = el.id.replace(id_regex, replacement);
        if (el.name) el.name = el.name.replace(id_regex, replacement);
    }

    function addForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        // You can only submit a maximum of 10 todo items 
        if (formCount < 1000) {
            // Clone a form (without event handlers) from the first form
            var row = $(".item:first").clone(false).get(0);
            // Insert it after the last form
            $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);

            // Remove the bits we don't want in the new row/form
            // e.g. error messages
            $(".errorlist", row).remove();
            $(row).children().removeClass("error");

            // Relabel or rename all the relevant bits
            $(row).children().children().each(function () {
                updateElementIndex(this, prefix, formCount);
                $(this).val("");
            });

            // Add an event handler for the delete item/form link 
            $(row).find(".delete").click(function () {
                return deleteForm(this, prefix);
            });
            // Update the total form count
            $("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1);
            window.location.href = "#erfassung"
        } // End if
        else {
            alert("Sorry, you can only enter a maximum of ten items.");
        }
        return false;
    }
    function addvarForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        // You can only submit a maximum of 10 todo items 
        if (formCount < 1000) {
            // Clone a form (without event handlers) from the first form
            var row = $(".item_var:first").clone(false).get(0);
            // Insert it after the last form
            $(row).removeAttr('id').hide().insertAfter(".item_var:last").slideDown(300);

            // Remove the bits we don't want in the new row/form
            // e.g. error messages
            $(".errorlist", row).remove();
            $(row).children().removeClass("error");

            // Relabel or rename all the relevant bits
            $(row).children().children().each(function () {
                updateElementIndex(this, prefix, formCount);
                $(this).val("");
            });

            // Add an event handler for the delete item/form link 
            $(row).find(".delete").click(function () {
                return deleteForm(this, prefix);
            });
            // Update the total form count
            $("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1);
            // Revalidate the fields
            $('myForm').data('validator', null);
            $.validator.unobtrusive.parse($('myForm'));
        } // End if
        else {
            alert("Sorry, you can only enter a maximum of ten items.");
        }
        return false;
    }
    // Register the click event handlers
    $("#add_attr").click(function () {
        return addForm(this, "attr");
    });

    $("#add_var").click(function () {
        return addvarForm(this, "var");
    });

});

</script>


</head>
<body>
<h2>Pr&uuml;fplan erstellen</h2>
<form id="myForm" action="" method="POST" class="bootstrap">{% csrf_token %}
    <div class="section">
        {{ pruefplan_form | crispy}}
    </div>
    <h2>Pruefschritte attributiv</h2>
    {{ pruefplan_attributiv_formset.management_form }}
    {% for form in pruefplan_attributiv_formset.forms %}
    <div class="item">
      {{ form | crispy }}
    </div>
    {% endfor %}
    <p><a id="add_attr" href="#">Prüfpunkt hinzufügen</a></p>
    <h2>Pruefschritte variabel</h2>
    {{ pruefplan_variable_formset.management_form }}
    {% for form in pruefplan_variable_formset.forms %}
    <div class="item_var">
      {{ form | crispy }}
    </div>
    {% endfor %}
    <p><a id="add_var" href="#">Prüfpunkt hinzufügen</a></p>


    <input type="submit" value=" Submit " />
</form>
</body>
</div>

POST dict:

    <QueryDict: {u'attr-0-prueftext_attributiv': [u'1', u'2'], u'var-INITIAL_FORMS':
 [u'0'], u'pruefmittel': [u'tt'],
 u'var-0-obere_grenze': [u'1'],
 u'var-0-prueftext_variabel': [u'1'], u'prueflink': [u'https://link.local'], u'var-0-soll': [u'1'], u'var-0-untere_grenze': [u'1'], u'pruefdatei': [u''], u'pruefintervall_obere_grenze': [u'12'],
 u'attr-MIN_NUM_FORMS': [u'0'], u'pruefintervall': [u'21'],
 u'pruefbild': [u''], u'csrfmiddlewaretoken': [u'2mw1tktwBUiheZ422Q2jlEygRQ18DuII'],
 u'var-MAX_NUM_FORMS': [u'10'], u'pruefplannummer': [u'56'], u'lagerort': [u'tt'], u'attr-TOTAL_FORMS': [u'2'], 
u'pruefintervall_untere_grenze': [u'12'], u'attr-MAX_NUM_FORMS': [u'10'], u'pruefanweisung': [u'tt'], 
u'var-MIN_NUM_FORMS': [u'0'],
 u'attr-INITIAL_FORMS': [u'0'],
 u'var-TOTAL_FORMS': [u'1']}>

更新

所以我发现了问题:

        function updateElementIndex(el, prefix, ndx) {
        var id_regex = new RegExp('(' + prefix + '-\\d+-)');
        var replacement = prefix + '-' + ndx + '-';
        if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex,
        replacement));
        if (el.id) el.id = el.id.replace(id_regex, replacement);
        if (el.name) el.name = el.name.replace(id_regex, replacement);
    }

不更新ID或名称。然而,“For”已更新。如果我纠正这个问题,一切都会变得很好。

那么我该如何解决这个问题呢?

1 个答案:

答案 0 :(得分:0)

此行帽将替换为:

$(row).children().children().each(function () {
                updateElementIndex(this, prefix, formCount);
                $(this).val("");

$(row).children().children().children().each(function () {
                updateElementIndex(this, prefix, formCount);
                $(this).val("");

由于HTML生成了一个带有3个嵌套元素的div

<div id="div_id_attr-0-prueftext_attributiv" class="form-group">
<label class="control-label " for="id_attr-0-prueftext_attributiv">    
</label>
<div class="controls ">
    <input id="id_attr-1-prueftext_attributiv" class="textinput    
     extInput form-control" type="text" name="attr-
     1-prueftext_attributiv" maxlength="64"></input>
</div>
</div>

使用两个.children()替换只能达到标签和控制而不是输入。