Django complex multiform views

I am not that good in coding, so take me easy. I would like to create/update view with multiple models in a single form , but need to dynamically add second and third model (need formsets) form into the view. That could be achieved by javascript , by copy empty forms.

here is model structure, need it to be scalable, but lets stack with 3 models.

What I need

1)present parent and second 2)hit resolve button , which will send ajax and all form data then I proces validate and get additional data and that generate third forms 3)save everything back to database , with appropriate ForeigKeys between models

models.py

from django.db import models

class Parrent(models.Model):
    data = models.CharField(max_length=30)

class Second(models.Model):
    parent = models.ForeignKey(Parrent, on_delete=models.CASCADE)
    data = models.CharField(max_length=30)

class Third(models.Model):
    second = models.ForeignKey(Second, on_delete=models.CASCADE)
    data = models.CharField(max_length=30)

forms.py

from django.forms import ModelForm
from myapp.models import Parrent, Second, Third 

class ParrentForm(ModelForm):
    class Meta:
        model = Parrent
        fields = ['data']

class SecondForm(ModelForm):
    class Meta:
        model = Second
        fields = ['data']

class ThirdForm(ModelForm):
    class Meta:
        model = Third 
        fields = ['data']

SecondFormSet = formset_factory(SecondForm, extra=1)
ThirdFormSet = formset_factory(ThirdForm, extra=1)

template.html

<!-- [ Template form second] start -->
<div id='template-second-form' class="card-body table-border-style hidden">
    {{ forms.second}}
    <br>
    <button type="button" class="btn  btn-danger delete_btn">Remove</button>
</div>
<!-- [ Template volume ] end -->
<!-- [ repeated for the third ] end -->
                                
<!-- [ FORM ] start -->
<form id='multi-form' method="post">{% csrf_token %}
    <div class="card-body table-border-style">
        {{ forms.parrent}}
    </div>
        <!-- [ Second list ] start -->
        <div id='second-list'>
            <!-- [ list all second elements here (javascript) ] -->
        </div>
        <!-- [ Second list ] end -->

        <div class="card-body table-border-style">
            <button id='add-second'type="button" class="btn  btn-primary">Add second</button>
            <button id='resolve'type="button" class="btn  btn-info">Resolve</button>
        </div>

test.js

const addNewSecondBtn= document.getElementById('add-second')

addNewSecondBtn.addEventListener('click', add_new_second_form)

function add_new_second_form(event) {
  if (event) {
    event.preventDefault()
  }
  // add new empty form element to html form
  const emptySecondFormEl = document.getElementById('template-second-form').cloneNode(true)
  emptySecondFormEl.classList.remove('hidden')
  const VolumeListEl = document.getElementById('second-list')
  VolumeListEl.append(emptyVolumeFormEl)
}

document.addEventListener('click', ({target: btn})=>{
  btn.matches('.delete_btn') && btn.parentNode.remove()
}, false);


$(document).ready(function() {

  $("#resolve").click(function () {
    var serialData = $("#multi_form").serializeArray()
    serialData = JSON.stringify(serialData);
    console.log(serialData)
    $.ajax({
      type: "GET",
      url: "/ajax/resolve/",
      data: {
        serialData: serialData,
      },
      success: function () {
        console.log("done");
      },
      error: function () {
        console.log("error");
      },
    });// & ajax
  });


}) //$ doc ready func

I would like to use class based view, I have browsed generic views , but seems to be not sane enought to understand what function I have to manually edit in order to get it work. Also checked some third party modules like better-forms -> not sure how to fit formsets inside and seems to be outdated (running django4) and multiform -> treat forms separately I need single form. Crypsi forms looks just for styling. I was looking at inline formset but not sure how to fit more then two models as there is always example only for two.

Back to Top