0

I'm looking for handle Django formsets. I would like to display the first form in my formset and be able to add multiple forms when I click over the adding button.

Up to now, I display my formset with extra=4 but I would like to set extra=1 and add extra when I click on new form button.

In my template I have :

{% block main %}

  <h2>{{title}}</h2>

  <div class="row publication-create">

    <form method="post" action="" enctype="multipart/form-data" novalidate class="col-md-8 col-md-offset-2">
      {% csrf_token %}
        <fieldset>
          <legend class="title"><span class="name">{% trans 'Publication form' %}</span></legend>
            {{ form|crispy }}
        </fieldset>
        <fieldset>
          <legend class="title"><span class="name">{% trans 'Document form' %}</span></legend>
          <button class="btn btn-default" type="button" data-toggle="collapse" data-target="#collapseDocument" aria-expanded="false" aria-controls="collapseDocument">
            {% trans 'Add document(s)' %}
          </button>
          <div class="collapse" id="collapseDocument">
            <div class="card card-body">
            {{ document_form|crispy }}
            </div>
          </div>
        </fieldset>
      <br>
      <input type="submit" class="btn btn-default" value="{% trans 'Save' %}" />
      <a href="{{request.META.HTTP_REFERER}}" class="btn btn-default">{% trans 'Cancel' %}</a>
    </form>
  </div>

{% endblock main %}

In my forms.py file I have :

DocumentFormSet = inlineformset_factory(Publication, Document, form=DocumentForm, extra=1)

And my view looks like this :

class PublicationCreateView(EdqmCreateView):
    """ Create publication with document form through formset """
    model = Publication
    template_name = 'publication_form.html'

    def get_context_data(self, **kwargs):
        context = super(PublicationCreateView, self).get_context_data(**kwargs)
        context['document_form'] = DocumentFormSet(self.request.POST or None, self.request.FILES or None)
        return context

    def form_valid(self, form):
        context = self.get_context_data()
        document = context['document_form']
        if document.is_valid():
            self.object = form.save()
            document.instance = self.object
            document.save()
        return super(PublicationCreateView, self).form_valid(form)

    def get_success_url(self):
        return reverse('publication-list-crud')

Result :

With my code, I added a button, but this button display 4 forms at the same time. I would like to display it one after the other. I think I need Javascript code ?

Thank you !

I read this post : Dynamically adding a form to a Django formset with Ajax But I don't overcome to reproduce the example with my script.

ChocoBomb
  • 301
  • 4
  • 15

1 Answers1

0

Since you only need max 4 forms you could hide 3 of them using javascript then incrementally show them as user click on the button.

Example:

var forms = [
    document.getElementById("form1");
    document.getElementById("form2");
    document.getElementById("form3");
    document.getElementById("form4");
]
var addButton = document.getElementById("addButton");
for(var i = 0 ; i < 3 ; i++){
    forms[i+1].style.display = "none";
}
var actForm = 1;

addButton.onclick = function(){
    if(actForm < 4){
        forms[actForm].style.display = 'block';
        actForm++;
    }
}

You'd still have to figure out id's of the forms, look at the produced html, i know django adds some in certain pattern.

However this is not a 'good' solution as this is very specific. One very nice way of doing so could be to have an ajax endpoint which returns the appropriate html depending on the form index.

user2177591
  • 238
  • 2
  • 12