<section class="no-padding-top no-padding-bottom">
<div class="container-fluid">
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">{% trans 'RECORD NEW SALE' %}</h1>
</div>
<form method="POST" class="form-validate" id="form_set">
{% csrf_token %}
{{ formset.management_form }}
<table id="formset" class="form">
{% for form in formset.forms %}
{% if forloop.first %}
<thead><tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr></thead>
{% endif %}
<tr class="{% cycle row1 row2 %}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<div id="form_set" style="display:none">
<table class='no_error'>
{{ form }}
</table>
</div>
</div>
<br>
<br>
</form>
<button class="btn btn-success" id="add_more">Add</button>
<button class="btn btn-primary" type="submit" form="form_set">Save</button>
</section>
and when I try to create a model instance with a form in template, I get this error:
IntegrityError at /new_sale.html
duplicate key value violates unique constraint "dashboard2_historical_recent_data_pkey"
DETAIL: Key (id)=(3) already exists.
I know that id is a django automatic field, I tried without it too, but I get the same output everytime. In my database, I have about 10000 rows, why would the id autofield would not increment starting at 10000?
Hi Ken, I updated my post to correct this id issue, it was a typo for this example. As far as the error, it indeed happens at formset_check.save() line. By tweaking id field datatype in postgresql, I can now upload several forms at once, but only one form per ‘reference’ get saved. How strange!
How are you rendering the form set? (Can you show the template?) One common mistake is not rendering all the hidden fields that are part of the form set.
Also, did you change your view to save the formset rather than the individual forms? (Saving the formset properly handles unused forms in the formset.)
Hi Kent, thanks for your advices, I updated my post to show how the formset is being rendered in template.
I have also tried saving the formset on its own in the view as such:
sorry it was an error, I have tried so many versions, I miss copied it. Anyways, things are still not working with this process, at this point I don’t know what else to try out.
I just noticed that clicking “add” to add a form in the template, create the number of formset already existing on the template. For instance, if there are 2 forms on the formset, clicking on “add” would create 2 new forms. Maybe this javascript code is causing the problem?
There’s a function in formsets to render a blank form. What I do is render an instance of the blank form in a hidden div, and then make a copy of it to add to my form.
<section class="no-padding-top no-padding-bottom">
<div class="container-fluid">
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">{% trans 'RECORD NEW SALE' %}</h1>
</div>
<form method="POST" class="form-validate" id="formset">
{% csrf_token %}
{{ formset.management_form }}
<table id="formset" class="form">
{% for form in formset.forms %}
{% if forloop.first %}
<thead><tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr></thead>
{% endif %}
<tr class="{% cycle row1 row2 %}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<div id="emptyform_wrapper" style="display:none">
<table class='no_error'>
{{ form }}
</table>
</div>
</div>
<br>
<br>
</form>
<button class="btn btn-success" id="add_more">Add</button>
<button class="btn btn-primary" type="submit" form="formset">Save</button>
</section>
<script type='text/javascript'>
$('#add_more').click(function () {
var form_idx = $('#id_form-TOTAL_FORMS').val();
$('#formset').append($('#emptyform_wrapper').html().replace(/__prefix__/g, form_idx));
$('#id_form-TOTAL_FORMS').val(parseInt(form_idx) + 1);
});
</script>
the only issue with this code is that the add button adds a form but it never gets displayed so the user needs to try saving to get django to show the “added” form saying that they cannot. be empty. Then saving and all works fine. Getting closer!
(This snippet comes from a really strange chunk of code, I wouldn’t necessarily do it this way again, but it worked for what we needed it to do at the time. Not that it really matters, but I believe this was for a case where we had multiple formsets on the same page, so we put the blank row at the end of the table. Anyway, it should give you an idea of what needs to be done.)