Add first version of send form data to email

This has been added in a generic way to allow defining form processing
backends. Sending the form data to an email is one of these backends -
others may include for instance call a web service with the form data (for
instance in a customer complains form we'd need to start a customer
complains workflow).

In any case, if the AbstractForm has a 'form_processing_backend'
attribute which should be a class, a new object of that class will be
generated and its process method will be called. The process method needs
two argumetns: The Page to pass any needed paramaters and the form to
actually pass the form data.

The form processing backends should inherit from the BaseFormProcessor
class (however probably this will be refactored to just use duck-typing
since I don't think that a base class offers anything here) and implement
the process method. Also, another useful method would be the
validate_usage to be called from the Form that uses the backend and
actually check that the form defines the correct fields - an example is
that for the email processor we need to define an email_to field in the
form. The validate_usage would need to raise an ImproperlyConfigured
exception if it has not been configured yet, however it has not been yet
implemented.
This commit is contained in:
Serafeim Papastefanos 2014-03-21 23:47:48 +02:00
parent b6aca526da
commit 9557bc6605
5 changed files with 68 additions and 8 deletions

View file

@ -0,0 +1,11 @@
from django.core.exceptions import ImproperlyConfigured
class BaseFormProcessor(object):
def __init__(self):
pass
def validate_usage(page):
return True
def process(self, page, form):
return NotImplemented

View file

@ -0,0 +1,17 @@
import datetime
from django.core.exceptions import ImproperlyConfigured
from .base import BaseFormProcessor
from wagtail.wagtailadmin import tasks
class EmailFormProcessor(BaseFormProcessor):
def __init__(self):
pass
def validate_usage(page):
return True
def process(self, page, form):
content = ', '.join([ x[1].label +': '+ form.data.get(x[0]) for x in form.fields.items() ])
tasks.send_email_task.delay("New " + page.title+" form submission at " + str(datetime.datetime.now()) , content, page.email_from, [page.email_to] )

View file

@ -55,8 +55,8 @@ class FormBuilder():
return django.forms.ChoiceField(widget=django.forms.RadioSelect, **options)
def create_checkboxes_field(self, field, options):
options['choices'] = map(lambda x: (x.strip(),x.strip()), field.choices.split(','))
options['initial'] = field.default_value.split(',')
options['choices'] = [ (x.strip(), x.strip()) for x in field.choices.split(',')]
options['initial'] = [ x.strip() for x in field.default_value.split(',') ]
return django.forms.MultipleChoiceField(widget=django.forms.CheckboxSelectMultiple, **options)
def create_checkbox_field(self, field, options):

View file

@ -9,6 +9,8 @@ import re
from wagtail.wagtailcore.models import Page, Orderable
from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
from wagtail.wagtailforms.backends.email import EmailFormProcessor
from modelcluster.fields import ParentalKey
from .forms import FormBuilder
@ -47,8 +49,8 @@ class AbstractFormFields(models.Model):
label = models.CharField(max_length=255, help_text=_('The label of the form field') )
field_type = models.CharField(max_length=16, choices = FORM_FIELD_CHOICES)
required = models.BooleanField(default=True)
choices = models.CharField(max_length=512, blank=True, help_text=_('Comma seperated list of choices'))
default_value = models.CharField(max_length=255, blank=True)
choices = models.CharField(max_length=512, blank=True, help_text=_('Comma seperated list of choices. Only applicable in checkboxes, radio and dropdown.'))
default_value = models.CharField(max_length=255, blank=True, help_text=_('Default value. Comma seperated values supported for checkboxes.'))
help_text = models.CharField(max_length=255, blank=True)
panels = [
@ -65,12 +67,12 @@ class AbstractFormFields(models.Model):
class AbstractForm(Page):
"""A Form Page. Pages with form should inhert from it"""
"""A Form Page. Pages implementing a form should inhert from it"""
form_builder = FormBuilder
is_abstract = True # Don't display me in "Add"
def __init__(self, *args, **kwargs):
super(Page, self).__init__(*args, **kwargs)
super(AbstractForm, self).__init__(*args, **kwargs)
if not hasattr(self, 'landing_page_template'):
template_wo_ext = re.match(HTML_EXTENSION_RE, self.template).group(1)
self.landing_page_template = template_wo_ext + '_landing.html'
@ -93,10 +95,14 @@ class AbstractForm(Page):
)
FormSubmission.objects.create(
form_data = json.dumps(form_data),
form_page = self.page_ptr,
form_page = self,
user = request.user,
)
# TODO: Do other things like sending email
# If we have a form_processing_backend call its process method
if hasattr(self, 'form_processing_backend'):
form_processor = self.form_processing_backend()
form_processor.process(self, self.form)
# render the landing_page
# TODO: It is much better to redirect to it
return render(request, self.landing_page_template, {
@ -111,6 +117,17 @@ class AbstractForm(Page):
})
class AbstractEmailForm(AbstractForm):
"""A Form Page that sends email. Pages implementing a form that should be send to an email should inhert from it"""
is_abstract = True # Don't display me in "Add"
form_processing_backend = EmailFormProcessor
email_to = models.CharField(max_length=255, )
email_from = models.CharField(max_length=255, )
class Meta:
abstract = True
######## TEST
class ConcreteFormFields(Orderable, AbstractFormFields):
@ -124,3 +141,18 @@ ConcreteForm.content_panels = [
FieldPanel('thank_you', classname="full"),
InlinePanel(ConcreteForm, 'form_fields', label="Form Fields"),
]
########
class ConcreteEmailFormFields(Orderable, AbstractFormFields):
page = ParentalKey('wagtailforms.ConcreteEmailForm', related_name='form_fields')
class ConcreteEmailForm(AbstractEmailForm):
thank_you = models.CharField(max_length=255)
ConcreteEmailForm.content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('thank_you', classname="full"),
FieldPanel('email_from', classname="full"),
FieldPanel('email_to', classname="full"),
InlinePanel(ConcreteEmailForm, 'form_fields', label="Form Fields"),
]