Form Customisation

Currently we have defined two different types of forms, one which just enables saving the submission and one to additionally email the results of the submission.

Custom basic form

You can easily add your own all you have to do is create a model that inherits from wagtailstreamforms.models.BaseForm add any additional fields or properties and this will be added to the cms admin area.

Example:

from wagtailstreamforms.models import BaseForm

class CustomForm(BaseForm):

    def process_form_submission(self, form):
        super(CustomForm, self).process_form_submission(form) # handles the submission saving
        # do your own stuff here

Custom email form

If you want to inherit the additional email sending functionality then inherit from wagtailstreamforms.models.AbstractEmailForm. The saving of the submission and sending of the email is handled in the process_form_submission so be sure to call super if overriding that method.

Example:

from wagtailstreamforms.models import AbstractEmailForm

class CustomEmailForm(AbstractEmailForm):
     """ As above with email sending. """

     def process_form_submission(self, form):
         super(CustomEmailForm, self).process_form_submission(form) # handles the submission saving and emailing
         # do your own stuff here

Custom email form with content

Here is an example of an email form that has an additional RichTextField rendered with the form. This is especially useful if your form is being rendered from the template tag and you dont want to slot it in a streamfield.

Model:

from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList, FieldPanel
from wagtail.wagtailcore.fields import RichTextField
from wagtailstreamforms.models import AbstractEmailForm, BaseForm


class EmailFormWithContent(AbstractEmailForm):
    """ A form with content that sends and email. """

    content = RichTextField(blank=True)

    content_panels = [
        FieldPanel('content', classname='full'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(AbstractEmailForm.settings_panels, heading='General'),
        ObjectList(AbstractEmailForm.field_panels, heading='Fields'),
        ObjectList(AbstractEmailForm.email_panels, heading='Email Submission'),
        ObjectList(content_panels, heading='Content'),
    ])

Template:

{% load wagtailcore_tags %}
<h2>{{ value.form.name }}</h2>
{% if value.form.content %}
   <div class="form-content">{{ value.form.content|richtext }}</div>
{% endif %}
<form action="{{ value.form_action }}" method="post" novalidate>
    {% csrf_token %}
    {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
    {% for field in form.visible_fields %}
        {% include 'streamforms/partials/form_field.html' %}
    {% endfor %}
    <input type="submit" value="{{ value.form.submit_button_text }}">
</form>

Custom form submission model

If you need to save additional data, you can use a custom form submission model. To do this, you need to:

  • Define a model that extends wagtailstreamforms.models.AbstractFormSubmission.
  • Override the get_submission_class and process_form_submission methods in your form model.

Example:

import json

from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.utils.translation import ugettext_lazy as _

from wagtail.wagtailcore.models import Page
from wagtailstreamforms.models import AbstractFormSubmission, BaseForm


class CustomForm(BaseForm):
    """ A form that saves the current user and page. """

    def get_data_fields(self):
        data_fields = super(ExampleForm, self).get_data_fields()
        data_fields += [
            ('user', _('User')),
            ('page', _('Page'))
        ]
        return data_fields

    def get_submission_class(self):
        return CustomFormSubmission

    def process_form_submission(self, form):
        if self.store_submission:
            self.get_submission_class().objects.create(
                form_data=json.dumps(form.cleaned_data, cls=DjangoJSONEncoder),
                form=self,
                page=form.page,
                user=form.user if not form.user.is_anonymous() else None
            )


class CustomFormSubmission(AbstractFormSubmission):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    page = models.ForeignKey(Page)

    def get_data(self):
        form_data = super(CustomFormSubmission, self).get_data()
        form_data.update({
            'page': self.page,
            'user': self.user
        })
        return form_data

Note

Its important to note here that the form.page and form.user seen above are passed in via the before_serve_page hook wagtailstreamforms.wagtail_hooks.process_form.

If you want to use a different method of saving the form and you require these you will need to pass them in yourself when adding request.POST to the form.

Example usage can be seen in Providing your own submission method

Reference

class wagtailstreamforms.models.BaseForm(*args, **kwargs)

A form base class, any form should inherit from this.

copy()

Copy this form and its fields.

get_data_fields()

Returns a list of tuples with (field_name, field_label).

get_form_fields()

Form expects form_fields to be declared. If you want to change backwards relation name, you need to override this method.

get_submission_class()

Returns submission class.

You can override this method to provide custom submission class. Your class must be inherited from AbstractFormSubmission.

process_form_submission(form)

Accepts form instance with submitted data. Creates submission instance if self.store_submission = True.

You can override this method if you want to have custom creation logic. For example, you want to additionally send an email.

specific

Return this form in its most specific subclassed form.

specific_class

Return the class that this page would be if instantiated in its most specific form

class wagtailstreamforms.models.AbstractEmailForm(*args, **kwargs)

A form that sends and email.

You can create custom form model based on this abstract model. For example, if you need a form that will send an email.

process_form_submission(form)

Process the form submission and send an email.

send_form_mail(form)

Send an email.

class wagtailstreamforms.models.AbstractFormSubmission(*args, **kwargs)

Data for a form submission.

You can create custom submission model based on this abstract model. For example, if you need to save additional data or a reference to a user.

get_data()

Returns dict with form data.

You can override this method to add additional data.