Django Formset: Submit two django forms at once.

Hello Devs, In this Post I'm gonna show you how can we submit two django forms at once and this is also called django inline forms, for example I have two forms one is for Question and another one is for Answers, and I want a inline form, like one question and that question have four answers, ok so let's see how can we do that.

Source Code:- 
https://github.com/ShivamRohilllaa/django-formset
Original Post:- https://www.webdevcodes.com/django/django-formset-submit-two-django-forms-at-once/

First of all create two tables in models.py:

class Question(models.Model):
    text = models.CharField(max_length=200, unique=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.text)

    #Reverse relationship
    def get_answers(self):
        return self.answers.all()   

class Answer(models.Model):
    text = models.CharField(max_length=200, verbose_name='Answer')
    correct = models.BooleanField()
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"question {self.question.text}, answer: {self.text}. correct: {self.correct}"

Now create modelforms in forms.py:

from django.forms.models import modelformset_factory


class QuestionsForm(forms.ModelForm):
    text = forms.CharField(label='Question', required=True)

    class Meta:
        model = Question
        fields = ['text']


AnswerFormset = modelformset_factory(
    Answer,
    fields=('text', 'correct'),
    extra=4,
    widgets={ 'text': forms.TextInput(attrs={ 'class': 'form-control','placeholder': 'Enter Answer here'}
            )
        }
)

import modelformset_factory then use modelformset_factory this in that form in which you want to show extra fields. for example one question have multiple answers, so we modelformset_factory in answer form

Now create views for that forms.

def add_questions(request):
    ques= QuestionsForm()
    formset = AnswerFormset(queryset=Answer.objects.none())
    if request.method=='POST':
        ques= QuestionsForm(request.POST)
        formset = AnswerFormset(request.POST)
        if ques.is_valid() and formset.is_valid():
            ques = ques.save()
            for form in formset:
                answer = form.save(commit=False)
                answer.question = ques
                answer.save() 
            return redirect('home')
    return render(request, "add-ques.html", {'ques':ques, 'formset':formset})


def home(request):
    ques = Question.objects.all()
    context = {'ques':ques}
    return render(request, 'index.html', context)

Now render that form in your template

<form action="." method='post'>
        {% csrf_token %}
        {% for field in ques %}
        <div class="form-group">
            <label for="text">{{field.label}}:</label>
            {{field}}
        </div>
        {% endfor %}
        {% comment %} {{ques}}
        {{formset}} {% endcomment %}
        {{ formset.management_form }}
        {% for field in formset %}
        <div class="form-group mt-5 mb-5">
          <label for="text">{{field.label}}</label>
          {{field.text}}
        </div>
        {% endfor %}
        <button type="submit" class="btn btn-primary">Submit</button>
      </form>

that's it and this is how your form look like

Source Code:- 
https://github.com/ShivamRohilllaa/django-formset

Thank you
Shivam Rohilla Python Developer

6