4

So I have set up the following codes for sample from followed by inline formset of its foreign key, sample detail. I also added some dynamic feature to it so that you could add more rows for the formset via Jquery. I got the Jquery section from http://stackoverflow.com/questions/501719/dynamically-adding-a-form-to-a-django-formset-with-ajax. I tried both implementation but it appears to have the same result. I am wondering if I did something wrong in the view.

views.py

def project_detail (request, project_id):
     project = Project.objects.get(id = project_id)
     sample_form = SampleForm(request.POST or None, request.FILES or None, instance = project)
     SampleInlineFormSet = inlineformset_factory(Sample, SampleDetail, form=SampleDetailForm, extra=1, can_delete = False)
     formset = SampleInlineFormSet(request.POST or None, request.FILES or None, prefix="nested")
     if request.method == "POST":

        if 'sampleform' in request.POST:
            if sample_form.is_valid() and formset.is_valid():
                 sample_temp = sample_form.save()
                 sample = Sample.objects.get(pk = sample_temp.pk)
                 objects = formset.save(commit=False)
                 for object in objects:
                       object.sample = sample
                       object.save()

                 messages.success(request, "Sucessfully Created New Sample Log" )
                 return HttpResponseRedirect(reverse('projstatus:project_detail', args=(project_id,)))           
     context = {'project' : project, "sample_form":sample_form, 'formset' : formset}
     return render(request, 'projstatus/detail.html', context)   

forms.py

<form method='POST' action='' enctype='multipart/form-data'>{% csrf_token %}
             {% crispy sample_form %}

             <div id="form_set">
                 {{ formset.management_form }}
                 {% for form in formset.forms %}
                     <table class='no_error'>

                         {{ form.as_table }}
                     </table>
                 {% endfor %}
             </div>
             <input type="button" value="Add More" id="add_more">

             <div id="empty_form" style="display:none">
                 <table class='no_error'>
                     {{ formset.empty_form.as_table }}

                 </table>
             </div>
             <script>
                 $('#add_more').click(function() {
                     var form_idx = $('#id_form-TOTAL_FORMS').val();
                     $('#form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
                     $('#id_form-TOTAL_FORMS').val(parseInt(form_idx) + 1);
                 });
             </script>


              <button type='submit' class='save btn btn-default' name = 'sampleform'>Save</button>      

             </form>

However, I have this problem that only the first formset instance is ever saved. no matter how many I put in dynamically. Could someone please help me?

Edit:

The look of the form enter image description here

POST data when using Jquery to add one more instance (2 instances in total) enter image description here

POST data when not using Jquery, setting extra = 2. (2 instances in total) enter image description here

5
  • 1
    The problem could be in your #add_more click handler. Compare the values of request.POST with and without Javascript (adjust extra in the view instead of clicking 'add more'), and make sure you are submitting the exact same data. Commented Nov 21, 2016 at 17:46
  • 1
    @Alasdair Hi thanks for the comments. I updated with POST data. Seems that it might be the "undefined" thing in Jquery case that is causing the problem Commented Nov 21, 2016 at 21:03
  • Your jQuery post data is missing nested-1-id, nested-1-location and so on. Commented Nov 21, 2016 at 21:51
  • @Alasdair Thanks! I still failed to see which part did I make mistake.... Anyway thanks so much Commented Nov 22, 2016 at 19:42
  • You may want to draw inspiration from how django.contrib.admin handles dynamically adding inline formset forms in inlines.js. Commented Nov 23, 2016 at 14:29

2 Answers 2

3
+50

I think your issue is with your javascript. It seems you took that snippet from another example that's floating around.

var form_idx = $('#id_form-TOTAL_FORMS').val();

For this to work, there needs to be an element with id of id_form-TOTAL_FORMS.

But I think your form will probably have this input with an id of something like id_nested-TOTAL_FORMS or something similar. As a result, I don't think your javascript is actually updating the Formset's management form data.

You should inspect your html on the page and see what the id of this input is. Also, use the javascript console to see what your JS code is really doing.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much! I tried to change #id_form-TOTAL_FORMS to #id_nested-TOTAL_FORMS and it works!
1

As with the previous answer, the nested-TOTAL_FORMS field value needs updating with the number of rows each time you add one. You're currently updating a field form-TOTAL_FORMS which doesn't exist.

Try updating the js from #id_form-TOTAL_FORMS to #id_nested-TOTAL_FORMS

There may also be a way to get the field ID as a template variable but that escapes me at the moment.

1 Comment

Thanks so much! I tried to change #id_form-TOTAL_FORMS to #id_nested-TOTAL_FORMS and it works!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.