Michael
Michael

Reputation: 4461

Shall I use django-dynamic-formset or is there a better solution?

A newbie's question.

There is a django-dynamic-formset.

We can see that the project was last updated 8 month ago: https://github.com/elo80ka/django-dynamic-formset/branches

As far as I can see, this application was well known some time ago. I mean that in the Internet I can find discussions and examples. But all materials are published some of years ago.

And there is a respectable site https://djangopackages.org/grids/g/forms/

There is no mentioning of django-dynamic-formset. This makes me a bit skeptical about the app.

Could you tell me what is the mainstream solution for dynamically adding a form to a Django formset?

By the way Django 1.10.

Upvotes: 0

Views: 2036

Answers (3)

Vathsala Bhat
Vathsala Bhat

Reputation: 1

<script>
  var form_num = 0;
  $(document).ready(function() {
        $("#additemsbutton").on('click',function(event)
        {
          ++form_num;
          $('#form_set').append($('#empty_form').html().replace(/__prefix__/g, form_num));
          $("#additems").val(form_num + 1);
       });
     });
</script>
<form action='' method="post">
    {% csrf_token %}
  <h1>Company details</h1>
    {{ company_form.as_p}}
  <h1>Project details</h1>
    {{ info_formset.management_form }}
    <div id="form_set">
      {% for form in info_formset %}
        {{ form.as_p }}
      {% endfor %}
    </div>
  <div id="empty_form" style="display:none">
      {{ info_formset.empty_form.as_p }}
  </div>
  <input type="hidden" value="1" name="additems" id="additems">
  <input type="button" id="additemsbutton" value="Add Project">
  <button type="submit" value="Submit" class="btn btn-primary">Submit</button>
</form>

Upvotes: 0

Lakshya Aggarwal
Lakshya Aggarwal

Reputation: 514

I have used the following method. The javascript increments a global variable form_num every time a new form is added to the webpage and in views.py that value is taken from POST data and replaces the form-TOTAL_FORMS value.

I have used empty_form as a template for a new form.

I had to make a copy of POST data because POST itself is immutable.

Template/index.html:

<script>
  var form_num = 0;
  $(document).ready(function() {
        $("#additemsbutton").on('click',function(event)
        {
          ++form_num;
          $('#form_set').append($('#empty_form').html().replace(/__prefix__/g, form_num));
          $("#additems").val(form_num + 1);
       });
     });
</script>
<form action='' method="post">
    {% csrf_token %}
  <h1>Company details</h1>
    {{ company_form.as_p}}
  <h1>Project details</h1>
    {{ info_formset.management_form }}
    <div id="form_set">
      {% for form in info_formset %}
        {{ form.as_p }}
      {% endfor %}
    </div>
  <div id="empty_form" style="display:none">
      {{ info_formset.empty_form.as_p }}
  </div>
  <input type="hidden" value="1" name="additems" id="additems">
  <input type="button" id="additemsbutton" value="Add Project">
  <button type="submit" value="Submit" class="btn btn-primary">Submit</button>
</form>

Views.py:

def index(request):
    extra_forms = 1
    InfoFormSet = inlineformset_factory(Company, Info, form=InfoForm, extra=extra_forms)
    if request.method == 'POST':
        print(request.POST)
        formset_dictionary_copy = request.POST.copy()
        formset_dictionary_copy['info_set-TOTAL_FORMS'] = int(
            formset_dictionary_copy['additems'])
        company_form = CompanyForm(formset_dictionary_copy)
        if company_form.is_valid():
            c = company_form.save()
        info_formset = InfoFormSet(formset_dictionary_copy)
        if info_formset.is_valid():
            formset = info_formset.save(commit=False)
            for i in formset:
                i.company = c
                i.save()
            return HttpResponseRedirect(reverse('pform:index'))

Upvotes: 1

souldeux
souldeux

Reputation: 3755

You can do it with Ajax, example and excellent explanation in this post. If you're concerned about those packages being maintained, this is the solution I'd suggest using.

Upvotes: 0

Related Questions