How to build form page in Wagtail

Michael Yin

Full Stack Developer

Last updated on Jan 02 2021

Table of Contents


In this Wagtail tutorial, I will show you how to build form page using Wagtail's FormBuilder, which is a very powerful feature. After you read this article, you will

  1. Understand how FormBuilder works and how to use it to build form page in your Wagtail project.

  2. Learn how to make FormBuilder work with Bootstrap theme using django-widget-tweaks

  3. Learn how to build contact page for your Wagtail blog, and you can check all submission in Wagtail's admin and your Email inbox.


If you have an existing Wagtail project, that would be good to go, if you are new to Wagtail. I recommend you to check wagtail-bootstarap-blog , this project is developed exclusively for my Wagtail tutorial series, it is a standard blog which is based on Bootstrap theme and Wagtail.

Step 1 - Create Model

First, please check INSTALLED_APPS of your Django settings file, make sure wagtail.contrib.forms is included.

And then we can start to create relevant data models in blog/

from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField

class FormField(AbstractFormField):
    page = ParentalKey('FormPage', related_name='custom_form_fields')

class FormPage(AbstractEmailForm):
    thank_you_text = RichTextField(blank=True)

    content_panels = AbstractEmailForm.content_panels + [
        InlinePanel('custom_form_fields', label="Form fields"),
        FieldPanel('thank_you_text', classname="full"),
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
        ], "Email Notification Config"),

    def get_form_fields(self):
        return self.custom_form_fields.all()

As you can see, FormField above is model of our form fields, FormPage is model of our form page, which extends AbstractEmailForm. AbstractEmailForm has the ability to send email after user submit on form page. It includes from_address, to_address, and subject, these fileds are used to send email notification. thank_you_text here is used to store the thanks message after use successfully submit.

If you do not need email notification of FormPage, just use AbstractForm instead and remove Email Notification Config fieldpanel from your model.

custom_form_fields here is a collection of form fields, we can later add different fields in Wagtail admin as we like.

The data model is almost done, now start migrate our database.

python makemigrations
python migrate

Step2 - Create Template

Now we start to create template for our form page. I have seen many people have trouble when trying to make the form page look elegant, so here I would show you a simple way to solve the problem. No need to touch css code.

Because Wagtail's has different output compared to Django's method, so django-crispy-forms can not work as expected, we need manually render the form fields and add some class value to it.

We can use django-widget-tweaks to add some css class to our form fields. Let's install it by using commands below

pip3 install django-widget-tweaks
# Add 'widget_tweaks' to INSTALLED_APPS

Then edit blog/templates/blog/form_page.html

{% extends "blog/base.html" %}
{% load static wagtailcore_tags widget_tweaks %}

{% block content %}


<form action="{% pageurl page %}" method="POST">
    {% csrf_token %}

    {% if form.non_field_errors %}
      <div class="alert alert-danger" role="alert">
        {% for error in form.non_field_errors %}
          {{ error }}
        {% endfor %}
    {% endif %}

    {% for field in form.visible_fields %}
      <div class="form-group">
        {{ field.label_tag }}
        {% render_field field class+="form-control" %}
    {% endfor %}

    <button type="submit" class="btn btn-primary" >Submit</button>

{% endblock %}

The key point here is {% render_field field class+="form-control" %}, we use render_field from widget_tweaks to render our form fields and make sure it contains css class form-control. Then Bootstrap can make our input tag looks better.

After use submit on form page sucessfully, we need to show some success message for him, that is why we need to create another template file here. The file name is form page template name plus _landing

Edit blog/templates/blog/form_page_landing.html

{% extends "blog/base.html" %}

{% load static wagtailcore_tags  wagtailimages_tags el_pagination_tags menu_tags %}

{% block content %}

<h2>{{ page.thank_you_text | richtext }}</h2>

{% endblock %}

Do you remember we have thank_you_text field in our form page model? The landing page would display the message you input in Wagtail admin, that is it!

Step3 - Config Email Test Env

To make us can check email notification sent by Wagtail in local dev environment, please make sure code below exists in settings/

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

The code above make Django print the Email message to our console, which make us easy to check.

We can launch our Django app now!

python runserver

Step4 - Enjoy Wagtail's Powerful FormBuilder

Now let's enjoy Wagtail's FormBuilder feature.

Login in Wagtail admin, and create Form page as child of our Blog Page

We set the title Contact, and add some fields in Form Fields, you can see you can add add many different form fields here, that is the power of Wagtail's FormBuilder, it is very flexible, People who have no coking skill can also create form page!

Next we config the email notification settings. At the end of form page, we can input email address, and subject.

When all edit job is done, click Publish button to make our form page live!

Now we can visit our form page at, and here is what it look like.

The form look good with our Bootstrap theme, and you can easily add, edit and remove form fields as you like in Wagtail admin, no coding is needed!

Next, we try to send submission in form page and check the results.

After we send submission, here is the thank you page.

The message on the thanks page can be also edited in Wagtail admin.

Step5 - Check Submissions

If we check our console, we can see an notification email has been sent out by Wagtail.

Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Contact Message Received
From: [email protected]
To: [email protected]
Date: Thu, 14 Jun 2018 09:22:52 -0000
Message-ID: <[email protected]>

Name: MichaelYin
Email: [email protected]
Message: Hello World!

From, To are the address we just set in form page, and the submission data has also been included in the email.

We can also check submission in Wagtail admin, which is very convenient.


In this Wagtail tutorial, we learned how to use Wagtail's FormBuilder to help us create contact page for our Wagtail bootstrap blog. We can also use it to build polls and surveys for our clients.

So where should you go next?

  • What happende if FormBuilder meets StreamField, you can check wagtailstreamforms to find more powerful features
  • django-widget-tweaks is to help people quickly use FormBuilder with Bootstrap, but building CSS file which can work directly with Wagtail Form is better solution.

Note: source code of this tutorial is available at wagtail-bootstarap-blog

You can also check the full list of my wagtail tutorial here wagtail tutorial series

Michael Yin

Michael is a Full Stack Developer from China who loves writing code, tutorials about Django, Wagtail CMS and React.

He has published some ebooks on leanpub and tech course on

He is also the founder of the AccordBox which provides the web development services.

Table of Contents

This book will teach you how to build a modern blog with Wagtail CMS

Read More


Get notified about new great Web Development Tutorial