Repository: UTNkar/moore

Issue:
Anonymous Contact Form
<!-- Do you want to ask a question? Are you looking for support? The system administrator can help you: admin@utn.se -->

### Prerequisites

* [X] Put an X between the brackets on this line if you have done all of the
following:
    * Reproduced the problem with clear cache.
    * (If running the application locally:) Made sure your running the newest version on the development branch
    * Checked that your issue isn't already filed: https://github.com/UTNkar/moore/issues

### Description

The website needs to have a feature to anonymously contact the study representatives within the Union. It should simply gather the subject and text and send it to a set e-mail address.

**note:** This should be a StreamField.

<!-- Please select the appropriate "topic category"/blue and "issue type"/yellow label -->


Discussion:
http://docs.wagtail.io/en/v1.11.1/reference/contrib/forms/index.html

Resolving patch:
diff --git a/website/home/migrations/0010_auto_20170718_0933.py b/website/home/migrations/0010_auto_20170718_0933.py
new file mode 100644
--- /dev/null
+++ b/website/home/migrations/0010_auto_20170718_0933.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.3 on 2017-07-18 07:33
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+import modelcluster.fields
+import wagtail.wagtailcore.blocks
+import wagtail.wagtailcore.fields
+import wagtail.wagtailimages.blocks
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('wagtailcore', '0039_collectionviewrestriction'),
+        ('home', '0009_contactpage'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='FormField',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
+                ('label', models.CharField(help_text='The label of the form field', max_length=255, verbose_name='label')),
+                ('field_type', models.CharField(choices=[('singleline', 'Single line text'), ('multiline', 'Multi-line text'), ('email', 'Email'), ('number', 'Number'), ('url', 'URL'), ('checkbox', 'Checkbox'), ('checkboxes', 'Checkboxes'), ('dropdown', 'Drop down'), ('radio', 'Radio buttons'), ('date', 'Date'), ('datetime', 'Date/time')], max_length=16, verbose_name='field type')),
+                ('required', models.BooleanField(default=True, verbose_name='required')),
+                ('choices', models.TextField(blank=True, help_text='Comma separated list of choices. Only applicable in checkboxes, radio and dropdown.', verbose_name='choices')),
+                ('default_value', models.CharField(blank=True, help_text='Default value. Comma separated values supported for checkboxes.', max_length=255, verbose_name='default value')),
+                ('help_text', models.CharField(blank=True, max_length=255, verbose_name='help text')),
+            ],
+            options={
+                'ordering': ['sort_order'],
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='FormPage',
+            fields=[
+                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
+                ('to_address', models.CharField(blank=True, help_text='Optional - form submissions will be emailed to these addresses. Separate multiple addresses by comma.', max_length=255, verbose_name='to address')),
+                ('from_address', models.CharField(blank=True, max_length=255, verbose_name='from address')),
+                ('subject', models.CharField(blank=True, max_length=255, verbose_name='subject')),
+                ('title_sv', models.CharField(max_length=255)),
+                ('intro_en', wagtail.wagtailcore.fields.StreamField((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html')), ('heading', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=True)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('image_description', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('icons', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('title', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock()))))), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('image_icons', wagtail.wagtailcore.blocks.StructBlock((('description', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('overlay', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)), ('button', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('logos', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailimages.blocks.ImageChooserBlock(), group='Noyce', icon='fa-pied-piper', label='Logos', template='blocks/logos.html')), ('counters', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('counters', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('value', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)))))), ('style', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('light', 'Light'), ('dark', 'Dark')]))))), ('columns', wagtail.wagtailcore.blocks.StructBlock((('columns', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('width', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Width out of 12', max_value=12, min_value=1)), ('content', wagtail.wagtailcore.blocks.StreamBlock((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html'))))))))),))), ('person', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('name', wagtail.wagtailcore.blocks.CharBlock()), ('role', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.RichTextBlock(required=False)), ('email', wagtail.wagtailcore.blocks.EmailBlock(required=False)))))), blank=True, verbose_name='English Introduction')),
+                ('intro_sv', wagtail.wagtailcore.fields.StreamField((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html')), ('heading', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=True)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('image_description', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('icons', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('title', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock()))))), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('image_icons', wagtail.wagtailcore.blocks.StructBlock((('description', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('overlay', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)), ('button', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('logos', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailimages.blocks.ImageChooserBlock(), group='Noyce', icon='fa-pied-piper', label='Logos', template='blocks/logos.html')), ('counters', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('counters', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('value', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)))))), ('style', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('light', 'Light'), ('dark', 'Dark')]))))), ('columns', wagtail.wagtailcore.blocks.StructBlock((('columns', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('width', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Width out of 12', max_value=12, min_value=1)), ('content', wagtail.wagtailcore.blocks.StreamBlock((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html'))))))))),))), ('person', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('name', wagtail.wagtailcore.blocks.CharBlock()), ('role', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.RichTextBlock(required=False)), ('email', wagtail.wagtailcore.blocks.EmailBlock(required=False)))))), blank=True, verbose_name='Swedish Introduction')),
+                ('thank_you_text_en', wagtail.wagtailcore.fields.StreamField((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html')), ('heading', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=True)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('image_description', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('icons', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('title', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock()))))), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('image_icons', wagtail.wagtailcore.blocks.StructBlock((('description', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('overlay', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)), ('button', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('logos', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailimages.blocks.ImageChooserBlock(), group='Noyce', icon='fa-pied-piper', label='Logos', template='blocks/logos.html')), ('counters', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('counters', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('value', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)))))), ('style', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('light', 'Light'), ('dark', 'Dark')]))))), ('columns', wagtail.wagtailcore.blocks.StructBlock((('columns', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('width', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Width out of 12', max_value=12, min_value=1)), ('content', wagtail.wagtailcore.blocks.StreamBlock((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html'))))))))),))), ('person', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('name', wagtail.wagtailcore.blocks.CharBlock()), ('role', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.RichTextBlock(required=False)), ('email', wagtail.wagtailcore.blocks.EmailBlock(required=False)))))), blank=True, verbose_name='English Thank You Text')),
+                ('thank_you_text_sv', wagtail.wagtailcore.fields.StreamField((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html')), ('heading', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=True)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('image_description', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('icons', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('title', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock()))))), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('image_icons', wagtail.wagtailcore.blocks.StructBlock((('description', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('overlay', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)), ('button', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('logos', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailimages.blocks.ImageChooserBlock(), group='Noyce', icon='fa-pied-piper', label='Logos', template='blocks/logos.html')), ('counters', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('counters', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('value', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)))))), ('style', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('light', 'Light'), ('dark', 'Dark')]))))), ('columns', wagtail.wagtailcore.blocks.StructBlock((('columns', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('width', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Width out of 12', max_value=12, min_value=1)), ('content', wagtail.wagtailcore.blocks.StreamBlock((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock(group='Basic', template='blocks/image.html'))))))))),))), ('person', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('name', wagtail.wagtailcore.blocks.CharBlock()), ('role', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.RichTextBlock(required=False)), ('email', wagtail.wagtailcore.blocks.EmailBlock(required=False)))))), blank=True, verbose_name='Swedish Thank You Text')),
+                ('form_title_en', models.CharField(blank=True, max_length=255, verbose_name='English Form Title')),
+                ('form_title_sv', models.CharField(blank=True, max_length=255, verbose_name='Swedish Form Title')),
+            ],
+            options={
+                'abstract': False,
+            },
+            bases=('wagtailcore.page',),
+        ),
+        migrations.AddField(
+            model_name='formfield',
+            name='page',
+            field=modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='form_fields', to='home.FormPage'),
+        ),
+    ]
diff --git a/website/home/models.py b/website/home/models.py
--- a/website/home/models.py
+++ b/website/home/models.py
@@ -8,6 +8,7 @@
 from wagtail.wagtailcore import blocks
 from wagtail.wagtailcore.fields import StreamField, RichTextField
 from wagtail.wagtailcore.models import Page, Orderable
+from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField
 from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
 
 from blocks.models import WAGTAIL_STATIC_BLOCKTYPES, PersonBlock
@@ -95,6 +96,83 @@ def get_context(self, request, *args, **kwargs):
     ])
 
 
+class FormField(AbstractFormField):
+    page = ParentalKey('FormPage', related_name='form_fields')
+
+
+class FormPage(AbstractEmailForm):
+    title_sv = models.CharField(max_length=255)
+    translated_title = TranslatedField('title', 'title_sv')
+
+    intro_en = StreamField(
+        WAGTAIL_STATIC_BLOCKTYPES,
+        verbose_name=_('English Introduction'),
+        blank=True,
+    )
+    intro_sv = StreamField(
+        WAGTAIL_STATIC_BLOCKTYPES,
+        verbose_name=_('Swedish Introduction'),
+        blank=True,
+    )
+    intro = TranslatedField('intro_en', 'intro_sv')
+
+    thank_you_text_en = StreamField(
+        WAGTAIL_STATIC_BLOCKTYPES,
+        verbose_name=_('English Thank You Text'),
+        blank=True,
+    )
+    thank_you_text_sv = StreamField(
+        WAGTAIL_STATIC_BLOCKTYPES,
+        verbose_name=_('Swedish Thank You Text'),
+        blank=True,
+    )
+    thank_you_text = TranslatedField('thank_you_text_en', 'thank_you_text_sv')
+
+    form_title_en = models.CharField(
+        verbose_name=_('English Form Title'),
+        max_length=255,
+        blank=True
+    )
+    form_title_sv = models.CharField(
+        verbose_name=_('Swedish Form Title'),
+        max_length=255,
+        blank=True,
+    )
+    form_title = TranslatedField('form_title_en', 'form_title_sv')
+
+    general_panels = [
+        InlinePanel('form_fields', label="Form fields"),
+        MultiFieldPanel([
+            FieldRowPanel([
+                FieldPanel('from_address', classname="col6"),
+                FieldPanel('to_address', classname="col6"),
+            ]),
+            FieldPanel('subject'),
+        ], "Email"),
+    ]
+
+    content_panels_en = AbstractEmailForm.content_panels + [
+        StreamFieldPanel('intro_en'),
+        FieldPanel('form_title_en', classname="full title"),
+        StreamFieldPanel('thank_you_text_en'),
+    ]
+
+    content_panels_sv = [
+        FieldPanel('title_sv', classname="full title"),
+        StreamFieldPanel('intro_sv'),
+        FieldPanel('form_title_sv', classname="full title"),
+        StreamFieldPanel('thank_you_text_sv'),
+    ]
+
+    edit_handler = TabbedInterface([
+        ObjectList(general_panels, heading=_('General')),
+        ObjectList(content_panels_en, heading=_('English')),
+        ObjectList(content_panels_sv, heading=_('Swedish')),
+        ObjectList(Page.promote_panels, heading=_('Promote')),
+        ObjectList(Page.settings_panels, heading=_('Settings')),
+    ])
+
+
 class HomePage(Page):
     # ---- General Page information ------
     title_sv = models.CharField(max_length=255)
diff --git a/website/materialize/templatetags/materialize.py b/website/materialize/templatetags/materialize.py
--- a/website/materialize/templatetags/materialize.py
+++ b/website/materialize/templatetags/materialize.py
@@ -8,12 +8,16 @@ def get_widget_name(field):
     return field.field.widget.__class__.__name__
 
 
-def append_classes(field):
+def append_classes(field, widget=''):
     field.field.label_suffix = ''
     classes = field.field.widget.attrs.get('class', '')
     classes += ' validate'
     if field.errors:
         classes += ' invalid'
+    if widget == 'Textarea':
+        classes += ' materialize-textarea'
+    if widget == 'DateInput':
+        classes += ' datepicker'
     field.field.widget.attrs['class'] = classes
 
 
@@ -29,12 +33,16 @@ def render_field(template, field, prefix=None):
 @register.simple_tag
 def materialize_field(field, prefix=None):
     widget = get_widget_name(field)
-    if widget in ['TextInput', 'EmailInput', 'PasswordInput', 'Select',
-                  'Textarea']:
-        append_classes(field)
+    if widget in ['EmailInput', 'DateInput', 'DateTimeInput', 'NumberInput',
+                  'PasswordInput', 'Select', 'Textarea', 'TextInput',
+                  'URLInput']:
+        append_classes(field, widget)
         return render_field('materialize/form/input.html', field, prefix)
+    elif widget == 'CheckboxInput':
+        return render_field('materialize/form/p_input.html', field)
+    # TODO: CheckboxSelectMultiple, DateTimeInput
     else:
-        return field.as_widget()
+        raise NotImplementedError('Widget %s not yet supported' % widget)
 
 
 @register.inclusion_tag('materialize/pagination.html')


Test patch: