1

I have 5 forms: MyForm, EducationForm, ExperienceForm, RecommendationForm, OtherDocumentsForm I want to disply them in one form template. I can not do it with CreateView because it only accepts one form class. How can I create single view for multiple forms?

class MyForm(forms.ModelForm):
    class Meta:
        model = UserForm_uz
        fields = 'all'

class EducationForm(forms.ModelForm):
    class Meta:
        model = Education_uz
        fields = 'all'

class ExperienceForm(forms.ModelForm):
    class Meta:
        model = Experience_uz
        fields = 'all'

class RecommendationForm(forms.ModelForm):
    class Meta:
        model = Recommendation_uz
        fields = 'all'

class OtherDocumentsForm(forms.ModelForm):
    class Meta:
        model = OtherDocuments
        fields = 'all'

I want all the forms to be submitted in a single request and single button. They related with foreignkey to each other EducationForm, ExperienceForm, RecommendationForm, OtherDocumentsForm connected to MyForm with foreignKey

My models:

from django.db import models
language_choices = [('1', 'Билмайман'),
                    ('2', 'Ёмон'),
                    ('3', 'Лугат ёрдамида'),
                    ('4', 'Ўртача'),
                    ('5', 'Яхши'),
                    ('6', 'Жуда яхши'), ]
approve_choices = [('Yes', 'Ха'),
                    ('No', 'Йўк')]
agreement_choices = [('Yes', 'Ха'),
                    ('No', 'Йўк')]
class UserForm_uz(models.Model):
    rasm = models.ImageField(upload_to='rasmlar',null=True,blank=True)
    lastName = models.CharField(max_length=200)
    firstName = models.CharField(max_length=200)
    middleName = models.CharField(max_length=200)
    birthData = models.DateField()
    nation = models.CharField(max_length=50)
    birthPlace = models.CharField(max_length=250)
    marriage_status = models.CharField(max_length=20)
    children = models.CharField(max_length=20)
    militaryResp = models.CharField(max_length=150)
    language_uzbek = models.CharField(choices=language_choices,max_length=150)
    language_russian = models.CharField(choices=language_choices,max_length=150)
    language_english = models.CharField(choices=language_choices,max_length=150)
    language_boshqa = models.CharField(max_length=50)
    computer_literacy = models.CharField(max_length=15)
    functional_resp = models.CharField(max_length=250)
    work_experience = models.CharField(max_length=200)
    yutuqlar = models.CharField(max_length=200)
    leaving_work_reason = models.CharField(max_length=200)
    main_skills = models.CharField(max_length=300)
    expected_salary = models.CharField(max_length=100)
    reasontoWork = models.CharField(max_length=300)
    relatives_company = models.CharField(max_length=300)
    criminal_history = models.CharField(max_length=250)
    homeNumber = models.CharField(max_length=15)
    phoneNumber = models.CharField(max_length=15)
    email = models.EmailField()
    additional_info = models.CharField(max_length=300)
    approve_info = models.CharField(choices=approve_choices,max_length=20)
    agreement = models.CharField(choices=agreement_choices,max_length=20)

    passport_file = models.FileField(upload_to='fayllar')
    diplom_file = models.FileField(upload_to='fayllar')
    trudovoyKnishka = models.FileField(upload_to='fayllar')
    fullName = models.CharField(max_length=100)

class Education_uz(models.Model):
    form = models.ForeignKey(
        UserForm_uz,
        on_delete=models.CASCADE,
    )
    startingDate = models.DateField()
    endingDate = models.DateField()
    name = models.CharField(max_length=200)
    degree = models.CharField(max_length=50)
    speciality = models.CharField(max_length=150)
    diplomSeriya = models.CharField(max_length=50)


class Experience_uz(models.Model):
    form = models.ForeignKey(
        UserForm_uz,
        on_delete=models.CASCADE,
    )
    startWorkDate = models.DateField()
    endWorkDate = models.DateField()
    name = models.CharField(max_length=100)
    lavozim = models.CharField(max_length=100)
    address = models.CharField(max_length=100)

class Recommendation_uz(models.Model):
    form = models.ForeignKey(
        UserForm_uz,
        on_delete=models.CASCADE,
    )
    fullName = models.CharField(max_length=150)
    workPlace = models.CharField(max_length=150)
    phoneAndEmail = models.CharField(max_length=100)

class OtherDocuments(models.Model):
    form = models.ForeignKey(
        UserForm_uz,
        on_delete=models.CASCADE,
    )
    file = models.FileField(upload_to='fayllar')
    comment = models.CharField(max_length=100)
  • Do you want all the forms to be submitted in a single request? How are these models related to each other? What have you tried so far? – Iain Shelvington Nov 19 '21 at 05:13
  • Yes, I want all the forms to be submitted in a single request and single button. They related with foreignkey to each other EducationForm, ExperienceForm, RecommendationForm, OtherDocumentsForm connected to MyForm with foreignKey – Mukhammad Ermatov Nov 19 '21 at 05:21

1 Answers1

0

Since MyForm will be submitted at the same time as the other forms you need to exclude the ForeignKey field to UserForm_uz from all the other models, the related object doesn't exist yet so you can't select it

class EducationForm(forms.ModelForm):
    class Meta:
        model = Education_uz
        # Repeated for all four forms
        exclude = ['form']  # Whatever the ForeignKey to UserForm_uz is named

Here's an example view that uses three of the forms (I missed out two to save typing). Give each form a prefix, this reduces the risk of having form fields with conflicting names. Validate them all in one go, if any form is invalid the view should not continue. Save MyForm first and use the output to pass to the other forms as the foreign key value

def my_view(request):
    if request.method == 'POST':
        my_form = MyForm(request.POST, request.FILES, prefix='user')
        education_form = EducationForm(request.POST, request.FILES, prefix='education')
        experience_form = ExperienceForm(request.POST, request.FILES, prefix='experience')
        if all([my_form.is_valid(), education_form.is_valid(), experience_form.is_valid()]):
            form = my_form.save()
            education = education_form.save(commit=False)
            education.form = form
            education.save()
            experience = experience_form.save(commit=False)
            experience.form = form
            experience.save()
            return redirect('some-view')
    else:
        my_form = MyForm(prefix='user')
        education_form = EducationForm(prefix='education')
        experience_form = ExperienceForm(prefix='experience')
    return render(request, 'template.html', {'my_form': my_form, 'education_form': education_form, 'experience_form': experience_form})

In your template (template.html) you'll need to render all forms in the same form tag

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ my_form }}
    {{ education_form }}
    {{ experience_form }}
    <input type="submit" />
</form>
Iain Shelvington
  • 31,030
  • 3
  • 31
  • 50
  • thanks bro! I did the same view, but it rendered nothing in my template. – Mukhammad Ermatov Nov 19 '21 at 06:11
  • do you have a telegram or whatsapp messenger? I really need your help bro – Mukhammad Ermatov Nov 19 '21 at 06:12
  • @MukhammadErmatov Added an example of the template. I'd rather not give out that info, let's see if we can't solve it via SO first? – Iain Shelvington Nov 19 '21 at 06:16
  • @IanShelvington it worked. I put {{ form.as_p }} at first. After changing template you provided, it correctly worked) another question: - Do I have to include fields = '__all__ ' with exclude = [ 'form' ] in forms.py – Mukhammad Ermatov Nov 19 '21 at 06:26
  • @MukhammadErmatov Glad it worked. No, you do not have to include `fields = '__all__'` if you have exclude – Iain Shelvington Nov 19 '21 at 06:27
  • Everything is okay. But when user submit this form, all the models should be connected to each other. How can I do that? I attached my models too on the question – Mukhammad Ermatov Nov 19 '21 at 06:33
  • when user is sending the form, he should have an opportunity to attach and send his education, experience and etc. information on the same form – Mukhammad Ermatov Nov 19 '21 at 06:35
  • @MukhammadErmatov where we did the `education = education_form.save(commit=False)` bit, you need to set `education.form = form` (the object from saving MyForm) and save. This sets the relatioships after the forms are validated and just before saving the objects. I updated the answer to better match your models – Iain Shelvington Nov 19 '21 at 06:35
  • Everything is fine bro. You are my hero thank you so much @IanShelvington – Mukhammad Ermatov Nov 19 '21 at 06:53