~ 2 min of reading

Manage two forms in one page

Depending on your situation, managing two forms in one page might not be straightforward. You might have tried to do it in a page with 2 forms and 2 submit buttons but that didn't work. Maybe you tried to use some javascript to manage the data of the two forms in the frontend but it was messy in the frontend and weird on the backend.

Two forms in one in the same page with django

Tipically, we all get to a point where we give up, build one form, and split the data in the backend.

But it doesn't have to be that way.

Here's a simple example of how to manage two forms in one page.

It actually uses 2 django forms in the same page. Both django forms are rendered in the same HTML form. All the data is sent to the backend in the same request.

In this example, on success, it simply displays a message to the user. You can take it from there and make it do what you need.

Here’s what it looks like:

Two forms in one in the same page with django
It's really basic, but it's just to get you started.

And here’s the code...

The HTML template:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Multiple Forms Example</title>
  </head>
  <body>
    

    <h1>Multiple Forms Example</h1>

    <form method="post">
      <div>
        <h2>Basic Information</h2>
        
      </div>

      <div>
        <h2>Password Change</h2>
        
      </div>

      <button type="submit">Submit Both Forms</button>
    </form>
  </body>
</html>

And the logic to manage it:

from django.shortcuts import render
from django import forms
from django.contrib import messages

class BasicForm(forms.Form):
    name = forms.CharField(label='Name', max_length=50)
    email = forms.EmailField(label='Email Address', max_length=100)

class PasswordChangeForm(forms.Form):
    old_password = forms.CharField(label='Current Password', widget=forms.PasswordInput, min_length=5)
    new_password = forms.CharField(label='New Password', widget=forms.PasswordInput, min_length=5)

    def clean_new_password(self):
        password = self.cleaned_data.get('new_password')
        if not any(char.isdigit() for char in password):
            raise forms.ValidationError("Password must contain at least one number.")
        if not any(not char.isalnum() for char in password):
            raise forms.ValidationError("Password must contain at least one symbol.")
        return password

def index(request):

    basic_form = BasicForm()
    advanced_form = PasswordChangeForm()

    if request.method == 'POST':
        basic_form = BasicForm(request.POST)
        advanced_form = PasswordChangeForm(request.POST)

        if basic_form.is_valid() and advanced_form.is_valid():
            basic_data = basic_form.cleaned_data
            advanced_data = advanced_form.cleaned_data

            # Do something with the data here

            messages.success(request, "Forms submitted successfully!")
    else:
        basic_form = BasicForm()
        advanced_form = PasswordChangeForm()

    context = {
        'basic_form': basic_form,
        'advanced_form': advanced_form,
    }

    return render(request, "multiform/index.html", context)

Alright. Here's all you need to do: Take both pieces. Copy them up into to your project. Add the views to your urls.py file. and you should be good to go.

By the way, I write about software development, web development, and Django. If you liked this post and were wondering how to get more... Join my inner circle (aka newsletter) in easy (and fast!) 4 steps.

  1. Fill your email.
  2. Fill your name (but only if you want).
  3. Smash the button. As hard as you can.
  4. There is no 4th step.

Add your name to join my inner circle (also known as newsletter 💌)

And that's a wrap. I hope you like it (I really do). If you did, hit one of those share buttons and spread it on your socials.