1

Problem: I have a problem with third form that has nested form at first it renders properly when I delete any child form that nested from all the form gets deleted. how can I fix that

End Goal: I wanted to built signup form that consists of three forms first form is basic login info, second form can have multiple instances of the single form where the user can add more form or remove it. and third form if nested from where the user also can add from or remove it. all these in under a single submit button.

What I have done: At this point i'm able to build all of the forms and stored first two forms that are basic signup info and second form that have multiple instances.

# model.py
class Vendor(BaseModel):
    user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True)
    address = models.CharField(max_length=100)
    mobile_no = models.CharField(max_length=12)
    gst = models.CharField(max_length=20)
    code = models.CharField(max_length=20)

    def __str__(self):
        if (self.user.first_name != None):
            return self.user.username
        else:   
            return self.user.first_name


# Material/s that vendor can process
class VendorMaterial(BaseModel):
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE)
    material = models.ForeignKey(Material, on_delete=models.CASCADE)


class VendorProcess(BaseModel):
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE)
    process = models.ForeignKey(ProcessType, on_delete=models.CASCADE)

    def _get_full_name(self):
        return self.process

    full_name = property(_get_full_name)

    def __str__(self):
        return self.process.name


# Machines available for the process with the vendor
class VendorProcessMachine(BaseModel):
    vendor_process = models.ForeignKey(VendorProcess, on_delete=models.CASCADE)
    brand_name = models.CharField(max_length=100, blank=True)
    accuracy = models.CharField(max_length=100, blank=True)
    bed_size = models.CharField(max_length=100, blank=True)
    year_of_manufacture = models.CharField(max_length=10, blank=True)
    quantity = models.CharField(max_length=50, blank=True)

    def __str__(self):
        return self.brand_name

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.forms import ModelForm, inlineformset_factory, formset_factory
from .models import User, Vendor, VendorMaterial, VendorProcess, VendorProcessMachine


class VendorSignupForm(UserCreationForm):
    first_name = forms.CharField(max_length=100, label="Name")
    mobile_no = forms.CharField(max_length=12)
    address = forms.CharField(max_length=100)
    gst = forms.CharField(max_length=12)
    username = forms.EmailField(max_length=64,label="Email")

    class Meta(UserCreationForm.Meta):
        model = User
        fields = ("first_name", "address", "username", "mobile_no","password1","password2",  "gst")
        exclude = ()

class VendorMaterialForm(ModelForm):
    class Meta:
        model = VendorMaterial
        fields = ("material",)


class VendorProcessForm(ModelForm):
    class Meta:
        model = VendorProcess
        fields = ('process',)

class VendorProcessMachineForm(ModelForm):
    class Meta:
        model = VendorProcessMachine
        fields = ("brand_name", "accuracy", "bed_size", "year_of_manufacture", "quantity")


VendorMaterialFormset = inlineformset_factory(Vendor, VendorMaterial, can_delete = False, extra=1, form=VendorMaterialForm)
VendorProcessFormset = inlineformset_factory(Vendor, VendorProcess, extra=1, can_delete=False, form=VendorProcessForm)
VendorProcessMachineFormset = inlineformset_factory(VendorProcess, VendorProcessMachine, extra=1, can_delete=False, form=VendorProcessMachineForm)

views.py

# view.py
class VendorSignUpView(CreateView):
    model = User
    form_class =VendorSignupForm
    template_name = 'signup.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.POST:
            context['vendor_material_formset'] = VendorMaterialFormset(self.request.POST, prefix="vendor_material_formset")
            context['vendor_process_formset'] = VendorProcessFormset(self.request.POST, prefix="vendor_process_formset")
            context['vendor_process_machine_formset'] = VendorProcessMachineFormset(self.request.POST, prefix="vendor_process_machine_formset")
        else:
            context['vendor_material_formset'] = VendorMaterialFormset(prefix="vendor_material_formset")
            context['vendor_process_formset'] = VendorProcessFormset(prefix="vendor_process_formset")
            context['vendor_process_machine_formset'] = VendorProcessMachineFormset(prefix="vendor_process_machine_formset")
        return context

    def form_valid(self, form):
        context = self.get_context_data()
        vendor_material = context['vendor_material_formset']
        user = form.save(commit=False)
        user.is_vendor = True
        user.is_staff = True
        user.email = form.cleaned_data.get('username')
        user=form.save()
        data = form.cleaned_data
        vendor = Vendor.objects.create(user=user, address=data['address'], mobile_no=data['mobile_no'],
        gst=data['gst'])
        # Save
        with transaction.atomic():
            if vendor_material.is_valid():
                print(vendor_material)
                vendor_material.instance = vendor
                vendor_material.save()
            # Vendor Process machine

        login(self.request, user)
        return redirect('home')

template.html

{% extends 'base.html' %}
{% load static %}
{% block content %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'formset/jquery.formset.js' %}"></script>
  <h2>Sign up</h2>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <table class="table">
    <div class="">
        {{ vendor_material_formset.management_form }}
        {% for vendor_material in vendor_material_formset %}
        <fieldset class="vendor_material_row">
        <legend>Material</legend>
        {{ vendor_material.as_p }}
        </fieldset>
       {% endfor %}
       </div>
     </table>
    <hr>
    <table> 
    <div>
        {{vendor_process_formset.management_form}}
        {% for vendor_process in vendor_process_formset %}
        <fieldset class="vendor_process_row">
        <legend>Vendor Process</legend>
        {{ vendor_process.as_p }}
            {{vendor_process_machine_formset.management_form}}
            <legend>Vendor Process Machine</legend>
            {% for vendor_process_machine in vendor_process_machine_formset %}
            <fieldset class="vendor_process_machine_row">
            {{ vendor_process_machine.as_p }}
            </fieldset>
            {% endfor %}
        </fieldset>
        {%endfor%}
    </div>
    </table>
    <input type="submit" name="submit" />
  </form>
<script>
    $('.vendor_material_row').formset({
        addText: 'Add Material',
        deleteText: 'Remove ',
        prefix: 'vendor_material_formset'
    });

    $('.vendor_process_row').formset({
        addText: 'Add Process',
        deleteText: 'Remove Process ',
        prefix: 'vendor_process_formset'
    });

    $('.vendor_process_machine_row').formset({
        addText: 'Add Process Machine',
        deleteText: 'Remove Process Machine',
        prefix: 'vendor_process_machine_formset'
    });
</script>
{% endblock %}
Nitesh Waghmare
  • 101
  • 1
  • 12

0 Answers0