[Fixed]-Saving dynamic formset with more than one form

1👍

Fixed it ! Only took a week. Here’s how it worked eventually. Views are largely unmodified, just added commit=False to save the list.

def routestepinfo(request, slug=None):
    RouteStepFormSet = formset_factory(RouteStepForm, formset = RequiredFormSet, extra=1)
    if request.method == 'POST':
        formset = RouteStepFormSet(request.POST)
        print formset
        if formset.is_valid():
            for form in formset.forms:
                form_item = form.save(commit=False)
                print form
                form_item.save()
                messages.success(request, "Record created")
            return redirect ("/buildpage/")
    else: 
        formset = RouteStepFormSet()
    return render(request, "buildpage/routestepinfo.html",{'formset':formset})

Javascript was the main thing that changed, with quite a few additions and quite a bit of SO help. The prefix was the first issue, and that was fixed by using formset.empty_form and modifying it from there. Another vital part was updating the total forms, which fixed the saving issue.

<script>
$(document).ready(function() {
    $('.add-item').click(function(ev) {
        ev.preventDefault();
        var count = $('#items-form-container').children().length;
        var tmplMarkup = $('#item-template').html();
        var compiledTmpl = tmplMarkup.replace(/__prefix__/g, count);
        $('div#items-form-container').append(compiledTmpl);

        // update form count
        $('#id_form-TOTAL_FORMS').attr('value', count+1);
        $('html, body').animate({
                scrollTop: $("#add-item-button").position().top-200
            }, 800);
    });
});
</script>

Finally the html. This combined some of my own stuff with a very helpful SO post(forgot the question it came from), where formset is generated as an empty form and cloned from there.:

        <div type="text/html" id="item-template">
          <table>
              {{ formset.empty_form.as_table }}
          </table>
          </div>
          <font face = Flexo>
          <form id= "myForm" method = 'POST' action="{% url 'buildpage:routestepinfo' %}" enctype="multipart/form-data">{% csrf_token %}
          {{ formset.management_form }}
          <div id="items-form-container">

          {% for form in formset.forms %}

          <div id="item-{{ forloop.counter0 }}">
          <table>
          {{form.as_table}}
          <table>
          </div>
          {% endfor %}
          </div>
          <a href="#" id="add-item-button" class="btn btn-info add-item">Add Step</a>
        <input type = "submit" name = "Submit Steps">
          </form>

Hope this helps some people. Cheers

Leave a comment