Как отобразить вложенный набор форм и сохранить в django? - PullRequest
1 голос
/ 25 февраля 2020

Проблема: У меня проблема с третьей формой, в которой сначала вложенная форма отображается правильно, когда я удаляю любую дочернюю форму, вложенную из всей формы, которая удаляется. как я могу это исправить

Конечная цель: Я хотел создать форму регистрации, состоящую из трех форм. Первая форма - это базовая c информация для входа, вторая форма может иметь несколько экземпляров одного форма, где пользователь может добавить больше формы или удалить ее. и третья форма, если она вложена, откуда пользователь также может добавить или удалить ее. все это под одной кнопкой отправки.

Что я сделал: На данный момент я могу построить все формы и сохранить первые две формы, которые основаны c информация о регистрации и вторая форма, которые имеют несколько экземпляров.

# 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')

шаблон. 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 %}
...