diff --git a/opentech/apply/funds/blocks.py b/opentech/apply/funds/blocks.py
index 416234725e7564b5441a3f697a47700c1f195a02..ccc4bb0db34a97b1c08c799cc3fc907c41e28f6d 100644
--- a/opentech/apply/funds/blocks.py
+++ b/opentech/apply/funds/blocks.py
@@ -1,3 +1,5 @@
+import json
+
 from django import forms
 from django.utils.translation import ugettext_lazy as _
 
@@ -15,6 +17,9 @@ class TitleBlock(ApplicationMustIncludeFieldBlock):
     name = 'title'
     description = 'The title of the project'
 
+    class Meta:
+        icon = 'tag'
+
 
 class ValueBlock(ApplicationMustIncludeFieldBlock):
     name = 'value'
@@ -41,6 +46,18 @@ class AddressFieldBlock(ApplicationMustIncludeFieldBlock):
         label = _('Address')
         icon = 'home'
 
+    def format_data(self, data):
+        # Based on the fields listed in addressfields/widgets.py
+        order_fields = [
+            'thoroughfare', 'premise', 'localityname', 'administrativearea', 'postalcode', 'country'
+        ]
+        address = json.loads(data)
+        return ', '.join(
+            address[field]
+            for field in order_fields
+            if address[field]
+        )
+
 
 class FullNameBlock(ApplicationMustIncludeFieldBlock):
     name = 'full_name'
@@ -50,6 +67,40 @@ class FullNameBlock(ApplicationMustIncludeFieldBlock):
         icon = 'user'
 
 
+class DurationBlock(ApplicationMustIncludeFieldBlock):
+    name = 'duration'
+    description = 'Duration'
+
+    DURATION_OPTIONS = {
+        1: "1 month",
+        2: "2 months",
+        3: "3 months",
+        4: "4 months",
+        5: "5 months",
+        6: "6 months",
+        7: "7 months",
+        8: "8 months",
+        9: "9 months",
+        10: "10 months",
+        11: "11 months",
+        12: "12 months",
+        18: "18 months",
+        24: "24 months",
+    }
+    field_class = forms.ChoiceField
+
+    def get_field_kwargs(self, *args, **kwargs):
+        field_kwargs = super().get_field_kwargs(*args, **kwargs)
+        field_kwargs['choices'] = self.DURATION_OPTIONS.items()
+        return field_kwargs
+
+    def format_data(self, data):
+        return self.DURATION_OPTIONS[int(data)]
+
+    class Meta:
+        icon = 'date'
+
+
 class ApplicationCustomFormFieldsBlock(CustomFormFieldsBlock, FormFieldsBlock):
     category = CategoryQuestionBlock(group=_('Custom'))
     required_blocks = ApplicationMustIncludeFieldBlock.__subclasses__()
diff --git a/opentech/apply/funds/migrations/0040_add_duration_stream_to_streamfield_definition.py b/opentech/apply/funds/migrations/0040_add_duration_stream_to_streamfield_definition.py
new file mode 100644
index 0000000000000000000000000000000000000000..8266e50d7546d0f7f7a0fcca1bf5b338965f08d7
--- /dev/null
+++ b/opentech/apply/funds/migrations/0040_add_duration_stream_to_streamfield_definition.py
@@ -0,0 +1,27 @@
+# Generated by Django 2.0.2 on 2018-08-10 08:28
+
+from django.db import migrations
+import opentech.apply.categories.blocks
+import wagtail.core.blocks
+import wagtail.core.blocks.static_block
+import wagtail.core.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('funds', '0039_add_rfps_and_sealed_rounds'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='applicationform',
+            name='form_fields',
+            field=wagtail.core.fields.StreamField((('text_markup', wagtail.core.blocks.RichTextBlock(group='Other', label='Paragraph')), ('char', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.core.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.core.blocks.CharBlock(label='Default value', required=False))), group='Fields')), ('text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('number', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.CharBlock(label='Default value', required=False))), group='Fields')), ('checkbox', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('default_value', wagtail.core.blocks.BooleanBlock(required=False))), group='Fields')), ('radios', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.core.blocks.ListBlock(wagtail.core.blocks.CharBlock(label='Choice')))), group='Fields')), ('dropdown', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.core.blocks.ListBlock(wagtail.core.blocks.CharBlock(label='Choice')))), group='Fields')), ('checkboxes', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('checkboxes', wagtail.core.blocks.ListBlock(wagtail.core.blocks.CharBlock(label='Checkbox')))), group='Fields')), ('date', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.DateBlock(required=False))), group='Fields')), ('time', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TimeBlock(required=False))), group='Fields')), ('datetime', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.DateTimeBlock(required=False))), group='Fields')), ('image', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('file', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('multi_file', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('rich_text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('category', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(help_text='Leave blank to use the default Category label', label='Label', required=False)), ('help_text', wagtail.core.blocks.TextBlock(label='Leave blank to use the default Category help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('category', opentech.apply.categories.blocks.ModelChooserBlock('categories.Category')), ('multi', wagtail.core.blocks.BooleanBlock(label='Multi select', required=False))), group='Custom')), ('title', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('value', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('email', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('address', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('full_name', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('duration', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')))),
+        ),
+        migrations.AlterField(
+            model_name='applicationsubmission',
+            name='form_fields',
+            field=wagtail.core.fields.StreamField((('text_markup', wagtail.core.blocks.RichTextBlock(group='Other', label='Paragraph')), ('char', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.core.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.core.blocks.CharBlock(label='Default value', required=False))), group='Fields')), ('text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('number', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.CharBlock(label='Default value', required=False))), group='Fields')), ('checkbox', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('default_value', wagtail.core.blocks.BooleanBlock(required=False))), group='Fields')), ('radios', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.core.blocks.ListBlock(wagtail.core.blocks.CharBlock(label='Choice')))), group='Fields')), ('dropdown', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('choices', wagtail.core.blocks.ListBlock(wagtail.core.blocks.CharBlock(label='Choice')))), group='Fields')), ('checkboxes', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('checkboxes', wagtail.core.blocks.ListBlock(wagtail.core.blocks.CharBlock(label='Checkbox')))), group='Fields')), ('date', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.DateBlock(required=False))), group='Fields')), ('time', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TimeBlock(required=False))), group='Fields')), ('datetime', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.DateTimeBlock(required=False))), group='Fields')), ('image', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('file', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('multi_file', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('rich_text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('category', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(help_text='Leave blank to use the default Category label', label='Label', required=False)), ('help_text', wagtail.core.blocks.TextBlock(label='Leave blank to use the default Category help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('category', opentech.apply.categories.blocks.ModelChooserBlock('categories.Category')), ('multi', wagtail.core.blocks.BooleanBlock(label='Multi select', required=False))), group='Custom')), ('title', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('value', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('email', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('address', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('full_name', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('duration', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')))),
+        ),
+    ]
diff --git a/opentech/apply/funds/models/submissions.py b/opentech/apply/funds/models/submissions.py
index 811ee371bb330642fd2b52d926375fca35917198..65ff60084487082b91d884ae7117ddb610dc558d 100644
--- a/opentech/apply/funds/models/submissions.py
+++ b/opentech/apply/funds/models/submissions.py
@@ -1,4 +1,5 @@
 import os
+from functools import partialmethod
 
 from django.conf import settings
 from django.contrib.auth import get_user_model
@@ -20,7 +21,7 @@ from wagtail.core.fields import StreamField
 from wagtail.contrib.forms.models import AbstractFormSubmission
 
 from opentech.apply.activity.messaging import messenger, MESSAGES
-from opentech.apply.stream_forms.blocks import UploadableMediaBlock
+from opentech.apply.stream_forms.blocks import FormFieldBlock, UploadableMediaBlock
 from opentech.apply.stream_forms.models import BaseStreamForm
 from opentech.apply.utils.blocks import MustIncludeFieldBlock
 
@@ -192,7 +193,44 @@ class AddTransitions(models.base.ModelBase):
         return super().__new__(cls, name, bases, attrs, **kwargs)
 
 
-class ApplicationSubmission(WorkflowHelpers, BaseStreamForm, AbstractFormSubmission, metaclass=AddTransitions):
+class ApplicationSubmissionMetaclass(AddTransitions):
+    def __new__(cls, name, bases, attrs, **kwargs):
+        cls = super().__new__(cls, name, bases, attrs, **kwargs)
+
+        # We want to access the redered display of the required fields.
+        # Treat in similar way to django's get_FIELD_display
+        for required_name in REQUIRED_BLOCK_NAMES:
+            partial_method_name = f'_{required_name}_method'
+            # We need to generate the partial method and the wrap it in property so
+            # we can access the required fields like normal fields. e.g. self.title
+            # Partial method requires __get__ to be called in order to bind it to the
+            # class properly this is using the <name> -> _<name>_method -> _get_REQUIRED_value
+            # call chain which instantiates each method correctly at the cost of an extra
+            # lookup
+            setattr(
+                cls,
+                partial_method_name,
+                partialmethod(cls._get_REQUIRED_value, name=required_name),
+            )
+            setattr(
+                cls,
+                f'{required_name}',
+                property(getattr(cls, partial_method_name)),
+            )
+            setattr(
+                cls,
+                f'get_{required_name}_display',
+                partialmethod(cls._get_REQUIRED_display, name=required_name),
+            )
+        return cls
+
+
+class ApplicationSubmission(
+        WorkflowHelpers,
+        BaseStreamForm,
+        AbstractFormSubmission,
+        metaclass=ApplicationSubmissionMetaclass,
+):
     field_template = 'funds/includes/submission_field.html'
 
     form_data = JSONField(encoder=DjangoJSONEncoder)
@@ -386,14 +424,6 @@ class ApplicationSubmission(WorkflowHelpers, BaseStreamForm, AbstractFormSubmiss
         self.ensure_user_has_account()
         self.process_file_data()
 
-    @property
-    def must_include(self):
-        return {
-            field.block.name: field.id
-            for field in self.form_fields
-            if isinstance(field.block, MustIncludeFieldBlock)
-        }
-
     def process_form_data(self):
         for field_name, field_id in self.must_include.items():
             response = self.form_data.pop(field_id, None)
@@ -479,36 +509,11 @@ class ApplicationSubmission(WorkflowHelpers, BaseStreamForm, AbstractFormSubmiss
     def can_have_determination(self):
         return self.in_determination_phase and not self.has_determination
 
-    @property
-    def raw_data(self):
-        data = self.form_data.copy()
-        for field_name, field_id in self.must_include.items():
-            response = data.pop(field_name)
-            data[field_id] = response
-        return data
-
-    def data_and_fields(self):
-        for stream_value in self.form_fields:
-            try:
-                data = self.form_data[stream_value.id]
-            except KeyError:
-                pass  # It was a named field or a paragraph
-            else:
-                yield data, stream_value
-
-    @property
-    def fields(self):
-        return [
-            field.render(context={'data': data})
-            for data, field in self.data_and_fields()
-        ]
-
-    def render_answers(self):
-        return mark_safe(''.join(self.fields))
-
     def prepare_search_values(self):
-        for data, stream in self.data_and_fields():
-            value = stream.block.get_searchable_content(stream.value, data)
+        for field_id in self.question_field_ids:
+            field = self.field(field_id)
+            data = self.data(field_id)
+            value = field.block.get_searchable_content(field.value, data)
             if value:
                 if isinstance(value, list):
                     yield ', '.join(value)
@@ -519,8 +524,19 @@ class ApplicationSubmission(WorkflowHelpers, BaseStreamForm, AbstractFormSubmiss
         for field in ['email', 'title']:
             yield getattr(self, field)
 
+    def get_absolute_url(self):
+        return reverse('funds:submissions:detail', args=(self.id,))
+
+    def __str__(self):
+        return f'{self.title} from {self.full_name} for {self.page.title}'
+
+    def __repr__(self):
+        return f'<{self.__class__.__name__}: {self.user}, {self.round}, {self.page}>'
+
+    # Methods for accessing data on the submission
+
     def get_data(self):
-        # Updated for JSONField
+        # Updated for JSONField - Not used but base get_data will error
         form_data = self.form_data.copy()
         form_data.update({
             'submit_time': self.submit_time,
@@ -528,21 +544,89 @@ class ApplicationSubmission(WorkflowHelpers, BaseStreamForm, AbstractFormSubmiss
 
         return form_data
 
-    def get_absolute_url(self):
-        return reverse('funds:submissions:detail', args=(self.id,))
+    @property
+    def raw_data(self):
+        # Returns the data mapped by field id instead of the data stored using the must include
+        # values
+        data = self.form_data.copy()
+        for field_name, field_id in self.must_include.items():
+            response = data.pop(field_name)
+            data[field_id] = response
+        return data
+
+    def field(self, id):
+        try:
+            return self.fields[id]
+        except KeyError as e:
+            try:
+                actual_id = self.must_include[id]
+            except KeyError:
+                raise e
+            else:
+                return self.fields[actual_id]
 
-    def __getattribute__(self, item):
-        # __getattribute__ allows correct error handling from django compared to __getattr__
-        # fall back to values defined on the data
-        if item in REQUIRED_BLOCK_NAMES:
-            return self.get_data()[item]
-        return super().__getattribute__(item)
+    def data(self, id):
+        try:
+            return self.form_data[id]
+        except KeyError as e:
+            try:
+                transposed_must_include = {v: k for k, v in self.must_include.items()}
+                actual_id = transposed_must_include[id]
+            except KeyError:
+                # We have most likely progressed application forms so the data isnt in form_data
+                return None
+            else:
+                return self.form_data[actual_id]
 
-    def __str__(self):
-        return f'{self.title} from {self.full_name} for {self.page.title}'
+    @property
+    def question_field_ids(self):
+        for field_id, field in self.fields.items():
+            if isinstance(field.block, FormFieldBlock):
+                yield field_id
 
-    def __repr__(self):
-        return f'<{self.__class__.__name__}: {self.user}, {self.round}, {self.page}>'
+    @property
+    def raw_fields(self):
+        # Field ids to field class mapping - similar to raw_data
+        return {
+            field.id: field
+            for field in self.form_fields
+        }
+
+    @property
+    def fields(self):
+        # ALl fields on the application
+        fields = self.raw_fields.copy()
+        for field_name, field_id in self.must_include.items():
+            response = fields.pop(field_id)
+            fields[field_name] = response
+        return fields
+
+    @property
+    def must_include(self):
+        return {
+            field.block.name: field.id
+            for field in self.form_fields
+            if isinstance(field.block, MustIncludeFieldBlock)
+        }
+
+    def render_answer(self, field_id, include_question=False):
+        field = self.field(field_id)
+        data = self.data(field_id)
+        return field.render(context={'data': data, 'include_question': include_question})
+
+    def render_answers(self):
+        answers = [
+            self.render_answer(field_id, include_question=True)
+            for field_id in self.question_field_ids
+            if field_id not in self.must_include
+        ]
+        return mark_safe(''.join(answers))
+
+    def _get_REQUIRED_display(self, name):
+        return self.render_answer(name)
+
+    def _get_REQUIRED_value(self, name):
+        return self.form_data[name]
 
 
 @receiver(post_transition, sender=ApplicationSubmission)
diff --git a/opentech/apply/funds/templates/funds/includes/rendered_answers.html b/opentech/apply/funds/templates/funds/includes/rendered_answers.html
index e5b7f88b2266a90a71dc67d714ee0dbfa40e05b9..e056156ba1d7ce22e34f4e22122b179d12ed17c0 100644
--- a/opentech/apply/funds/templates/funds/includes/rendered_answers.html
+++ b/opentech/apply/funds/templates/funds/includes/rendered_answers.html
@@ -8,7 +8,7 @@
 
     <div>
         <h5>Project Duration</h5>
-        <p>{{ object.value }}</p>
+        <p>{{ object.get_duration_display }}</p>
     </div>
 
     <div>
@@ -20,6 +20,10 @@
         <h5>Email</h5>
         <p>{{ object.email }}</p>
     </div>
+    <div class="grid__cell--span-two">
+        <h5>Address</h5>
+        <p>{{ object.get_address_display }}</p>
+    </div>
 </div>
 <div class="rich-text rich-text--answers">
     {{ object.render_answers }}
diff --git a/opentech/apply/funds/tests/factories/blocks.py b/opentech/apply/funds/tests/factories/blocks.py
index 8d378e36123893fe29af73ade86a4f2c346fc4d8..77cc38d4c0f70518bdb3cb58e07eacdf48835dbc 100644
--- a/opentech/apply/funds/tests/factories/blocks.py
+++ b/opentech/apply/funds/tests/factories/blocks.py
@@ -2,9 +2,17 @@ import random
 import factory
 
 from opentech.apply.funds import blocks
-from opentech.apply.stream_forms.testing.factories import FormFieldBlockFactory, CharFieldBlockFactory, \
-    NumberFieldBlockFactory, RadioFieldBlockFactory, ImageFieldBlockFactory, FileFieldBlockFactory, \
-    MultiFileFieldBlockFactory, StreamFieldUUIDFactory
+from opentech.apply.stream_forms.testing.factories import (
+    CharFieldBlockFactory,
+    FileFieldBlockFactory,
+    FormFieldBlockFactory,
+    ImageFieldBlockFactory,
+    MultiFileFieldBlockFactory,
+    NumberFieldBlockFactory,
+    RadioFieldBlockFactory,
+    ParagraphBlockFactory,
+    StreamFieldUUIDFactory,
+)
 from opentech.apply.utils.testing.factories import RichTextFieldBlockFactory
 
 __all__ = ['CustomFormFieldsFactory', 'TitleBlockFactory', 'EmailBlockFactory', 'FullNameBlockFactory', 'ValueFieldBlockFactory']
@@ -31,6 +39,16 @@ class FullNameBlockFactory(FormFieldBlockFactory):
         model = blocks.FullNameBlock
 
 
+class DurationBlockFactory(FormFieldBlockFactory):
+    class Meta:
+        model = blocks.DurationBlock
+
+    @classmethod
+    def make_answer(cls, params=dict()):
+        choices = list(blocks.DurationBlock.DURATION_OPTIONS.keys())
+        return random.choice(choices)
+
+
 class ValueFieldBlockFactory(FormFieldBlockFactory):
     class Meta:
         model = blocks.ValueBlock
@@ -41,6 +59,7 @@ class ValueFieldBlockFactory(FormFieldBlockFactory):
 
 
 CustomFormFieldsFactory = StreamFieldUUIDFactory({
+    'duration': DurationBlockFactory,
     'title': TitleBlockFactory,
     'value': ValueFieldBlockFactory,
     'email': EmailBlockFactory,
@@ -52,4 +71,5 @@ CustomFormFieldsFactory = StreamFieldUUIDFactory({
     'image': ImageFieldBlockFactory,
     'file': FileFieldBlockFactory,
     'multi_file': MultiFileFieldBlockFactory,
+    'text_markup': ParagraphBlockFactory,
 })
diff --git a/opentech/apply/funds/tests/factories/models.py b/opentech/apply/funds/tests/factories/models.py
index 286c340cd1fd4a05721107d15625c0a5aa5ec4cc..cffdc36f173ab0db015ca56f1b1d5ebc88774158 100644
--- a/opentech/apply/funds/tests/factories/models.py
+++ b/opentech/apply/funds/tests/factories/models.py
@@ -1,4 +1,3 @@
-from collections import defaultdict
 import datetime
 
 import factory
@@ -42,25 +41,6 @@ __all__ = [
 ]
 
 
-def build_form(data, prefix=''):
-    if prefix:
-        prefix += '__'
-
-    extras = defaultdict(dict)
-    for key, value in data.items():
-        if 'form_fields' in key:
-            _, field, attr = key.split('__')
-            extras[field][attr] = value
-
-    form_fields = {}
-    for i, field in enumerate(blocks.CustomFormFieldsFactory.factories):
-        form_fields[f'{prefix}form_fields__{i}__{field}__'] = ''
-        for attr, value in extras[field].items():
-            form_fields[f'{prefix}form_fields__{i}__{field}__{attr}'] = value
-
-    return form_fields
-
-
 class FundTypeFactory(wagtail_factories.PageFactory):
     class Meta:
         model = FundType
@@ -89,16 +69,14 @@ class FundTypeFactory(wagtail_factories.PageFactory):
     @factory.post_generation
     def forms(self, create, extracted, **kwargs):
         if create:
-            from opentech.apply.review.tests.factories.models import build_form as review_build_form, ReviewFormFactory
-            fields = build_form(kwargs, prefix='form')
-            review_fields = review_build_form(kwargs)
+            from opentech.apply.review.tests.factories.models import ReviewFormFactory
             for _ in self.workflow.stages:
                 # Generate a form based on all defined fields on the model
                 ApplicationBaseFormFactory(
                     application=self,
-                    **fields,
+                    **kwargs,
                 )
-                ReviewFormFactory(**review_fields)
+                ReviewFormFactory(**kwargs)
 
 
 class RequestForPartnersFactory(FundTypeFactory):
@@ -144,12 +122,11 @@ class RoundFactory(wagtail_factories.PageFactory):
     @factory.post_generation
     def forms(self, create, extracted, **kwargs):
         if create:
-            fields = build_form(kwargs, prefix='form')
             for _ in self.workflow.stages:
                 # Generate a form based on all defined fields on the model
                 RoundBaseFormFactory(
                     round=self,
-                    **fields,
+                    **kwargs,
                 )
 
 
@@ -184,12 +161,11 @@ class LabFactory(wagtail_factories.PageFactory):
     @factory.post_generation
     def forms(self, create, extracted, **kwargs):
         if create:
-            fields = build_form(kwargs, prefix='form')
             for _ in self.workflow.stages:
                 # Generate a form based on all defined fields on the model
                 LabBaseFormFactory(
                     lab=self,
-                    **fields,
+                    **kwargs,
                 )
 
 
@@ -236,11 +212,6 @@ class ApplicationSubmissionFactory(factory.DjangoModelFactory):
         if create and reviewers:
             self.reviewers.set(reviewers)
 
-    @classmethod
-    def _generate(cls, strat, params):
-        params.update(**build_form(params))
-        return super()._generate(strat, params)
-
 
 class SealedSubmissionFactory(ApplicationSubmissionFactory):
     page = factory.SubFactory(RequestForPartnersFactory)
diff --git a/opentech/apply/funds/tests/test_models.py b/opentech/apply/funds/tests/test_models.py
index 44b07e3891733bd7d965a3a58d94d785edb59433..9b21854c42f8127783fd6889788ba0b09b6a4293 100644
--- a/opentech/apply/funds/tests/test_models.py
+++ b/opentech/apply/funds/tests/test_models.py
@@ -172,7 +172,7 @@ class TestRoundModelWorkflowAndForms(TestCase):
         del self.round.parent_page
         form = self.round.forms.first().form
         # Not ideal, would prefer better way to create the stream values
-        new_field = CustomFormFieldsFactory.generate(None, {'0__email__': ''})
+        new_field = CustomFormFieldsFactory.generate(None, {})
         form.form_fields = new_field
         form.save()
         for round_form, fund_form in itertools.zip_longest(self.round.forms.all(), self.fund.forms.all()):
@@ -204,7 +204,8 @@ class TestFormSubmission(TestCase):
 
         page = page or self.round_page
         fields = page.get_form_fields()
-        data = {k: v for k, v in zip(fields, ['project', 0, email, name])}
+        # This needs to match the order of the fields defined on the form factory
+        data = {k: v for k, v in zip(fields, [1, 'project', 0, email, name])}
         request = make_request(user, data, method='post', site=self.site)
 
         try:
@@ -419,3 +420,28 @@ class TestApplicationSubmission(TestCase):
         submission.form_data = {'title': title}
         submission.create_revision(draft=True)
         self.assertEqual(submission.revisions.count(), 2)
+
+
+class TestSubmissionRenderMethods(TestCase):
+    def test_must_include_not_included_in_answers(self):
+        submission = ApplicationSubmissionFactory()
+        answers = submission.render_answers()
+        for name in submission.must_include:
+            field = submission.field(name)
+            self.assertNotIn(field.value['field_label'], answers)
+
+    def test_normal_answers_included_in_answers(self):
+        submission = ApplicationSubmissionFactory()
+        answers = submission.render_answers()
+        for field_name in submission.question_field_ids:
+            if field_name not in submission.must_include:
+                field = submission.field(field_name)
+                self.assertIn(field.value['field_label'], answers)
+
+    def test_paragraph_not_rendered_in_answers(self):
+        rich_text_label = 'My rich text label!'
+        submission = ApplicationSubmissionFactory(
+            form_fields__text_markup__value=rich_text_label
+        )
+        answers = submission.render_answers()
+        self.assertNotIn(rich_text_label, answers)
diff --git a/opentech/apply/review/tests/factories/models.py b/opentech/apply/review/tests/factories/models.py
index 2be83c8a6bcd513a694b4cc9bec23f03c7f4711a..79a82eb4b6b3052a4a02bb00dde3aff66d3600b4 100644
--- a/opentech/apply/review/tests/factories/models.py
+++ b/opentech/apply/review/tests/factories/models.py
@@ -1,5 +1,3 @@
-from collections import defaultdict
-
 import factory
 
 from opentech.apply.funds.models.forms import ApplicationBaseReviewForm
@@ -13,27 +11,9 @@ from ...views import get_fields_for_stage
 
 from . import blocks
 
-__all__ = ['ReviewFactory', 'ReviewFormFactory', 'ApplicationBaseReviewFormFactory',
-           'ReviewFundTypeFactory', 'ReviewApplicationSubmissionFactory']
-
-
-def build_form(data, prefix=''):
-    if prefix:
-        prefix += '__'
-
-    extras = defaultdict(dict)
-    for key, value in data.items():
-        if 'form_fields' in key:
-            _, field, attr = key.split('__')
-            extras[field][attr] = value
-
-    form_fields = {}
-    for i, field in enumerate(blocks.ReviewFormFieldsFactory.factories):
-        form_fields[f'{prefix}form_fields__{i}__{field}__'] = ''
-        for attr, value in extras[field].items():
-            form_fields[f'{prefix}form_fields__{i}__{field}__{attr}'] = value
-
-    return form_fields
+__all__ = ['ReviewFactory', 'ReviewFormFactory',
+           'ApplicationBaseReviewFormFactory', 'ReviewFundTypeFactory',
+           'ReviewApplicationSubmissionFactory']
 
 
 class ReviewFormDataFactory(factory.DictFactory, metaclass=AddFormFieldsMetaclass):
@@ -64,7 +44,11 @@ class ReviewFactory(factory.DjangoModelFactory):
     submission = factory.SubFactory(ApplicationSubmissionFactory)
     author = factory.SubFactory(StaffFactory)
     form_fields = blocks.ReviewFormFieldsFactory
-    form_data = factory.SubFactory(ReviewFormDataFactory, form_fields=factory.SelfAttribute('..form_fields'), submission=factory.SelfAttribute('..submission'))
+    form_data = factory.SubFactory(
+        ReviewFormDataFactory,
+        form_fields=factory.SelfAttribute('..form_fields'),
+        submission=factory.SelfAttribute('..submission'),
+    )
     is_draft = False
     recommendation = NO
     score = 0
@@ -89,12 +73,11 @@ class ReviewFundTypeFactory(FundTypeFactory):
     @factory.post_generation
     def review_forms(self, create, extracted, **kwargs):
         if create:
-            fields = build_form(kwargs, prefix='form')
             for _ in self.workflow.stages:
                 # Generate a form based on all defined fields on the model
                 ApplicationBaseReviewFormFactory(
                     application=self,
-                    **fields
+                    **kwargs
                 )
 
 
diff --git a/opentech/apply/stream_forms/blocks.py b/opentech/apply/stream_forms/blocks.py
index 903f232283e80dfb22b0fa149d045c8c65b5f344..77692d430db347d4f637f0761c874160f43d6726 100644
--- a/opentech/apply/stream_forms/blocks.py
+++ b/opentech/apply/stream_forms/blocks.py
@@ -50,9 +50,20 @@ class FormFieldBlock(StructBlock):
         return self.get_field_class(struct_value)(
             **self.get_field_kwargs(struct_value))
 
+    def get_context(self, value, parent_context):
+        context = super().get_context(value, parent_context)
+        parent_context['data'] = self.format_data(parent_context['data']) or self.no_response()
+        return context
+
     def get_searchable_content(self, value, data):
         return str(data)
 
+    def format_data(self, data):
+        return data
+
+    def no_responose(self):
+        return "No response"
+
 
 class OptionalFormFieldBlock(FormFieldBlock):
     required = BooleanBlock(label=_('Required'), required=False)
@@ -126,6 +137,9 @@ class CheckboxFieldBlock(FormFieldBlock):
     def get_searchable_content(self, value, data):
         return None
 
+    def no_responose(self):
+        return False
+
 
 class RadioButtonsFieldBlock(OptionalFormFieldBlock):
     choices = ListBlock(CharBlock(label=_('Choice')))
diff --git a/opentech/apply/stream_forms/templates/stream_forms/render_field.html b/opentech/apply/stream_forms/templates/stream_forms/render_field.html
index 049375a32c6fc5d22bf2a4516b101452ffbbb17c..8826fee6c0450155b406543ff9f1afd5d40e18fd 100644
--- a/opentech/apply/stream_forms/templates/stream_forms/render_field.html
+++ b/opentech/apply/stream_forms/templates/stream_forms/render_field.html
@@ -1,4 +1,10 @@
+{% if include_question %}
 <div>
     <h5>{{ value.field_label }}</h5>
-    <div>{% block data_display %}{{ data|default:"No response" }}{% endblock %}</div>
+{% endif %}
+
+    <div>{% block data_display %}{{ data }}{% endblock %}</div>
+
+{% if include_question %}
 </div>
+{% endif %}
diff --git a/opentech/apply/stream_forms/testing/factories.py b/opentech/apply/stream_forms/testing/factories.py
index 1d03a5670b7a3c7978245cb81a10ae1a8698949b..dfccb6bf957c067335c2f011f7f7d4a29025e96c 100644
--- a/opentech/apply/stream_forms/testing/factories.py
+++ b/opentech/apply/stream_forms/testing/factories.py
@@ -5,14 +5,16 @@ import uuid
 from django.core.files.uploadedfile import InMemoryUploadedFile
 
 import factory
-from wagtail.core.blocks import CharBlock
+from wagtail.core.blocks import RichTextBlock
+from wagtail.core.rich_text import RichText
 import wagtail_factories
 
 from opentech.apply.stream_forms import blocks as stream_blocks
 
-__all__ = ['CharBlockFactory', 'FormFieldBlockFactory', 'CharFieldBlockFactory', 'NumberFieldBlockFactory',
-           'RadioFieldBlockFactory', 'UploadableMediaFactory', 'ImageFieldBlockFactory', 'FileFieldBlockFactory',
-           'MultiFileFieldBlockFactory']
+__all__ = ['FormFieldBlockFactory', 'CharFieldBlockFactory',
+           'NumberFieldBlockFactory', 'RadioFieldBlockFactory',
+           'UploadableMediaFactory', 'ImageFieldBlockFactory',
+           'FileFieldBlockFactory', 'MultiFileFieldBlockFactory']
 
 
 class AnswerFactory(factory.Factory):
@@ -28,6 +30,7 @@ class AddFormFieldsMetaclass(factory.base.FactoryMetaClass):
             wrapped_factories = {
                 k: factory.SubFactory(AnswerFactory, sub_factory=v)
                 for k, v in field_factory.factories.items()
+                if issubclass(v, FormFieldBlockFactory)
             }
             attrs.update(wrapped_factories)
         return super().__new__(mcs, class_name, bases, attrs)
@@ -63,13 +66,20 @@ class FormDataFactory(factory.Factory, metaclass=AddFormFieldsMetaclass):
         return form_data
 
 
-class CharBlockFactory(wagtail_factories.blocks.BlockFactory):
+class ParagraphBlockFactory(wagtail_factories.blocks.BlockFactory):
     class Meta:
-        model = CharBlock
+        model = RichTextBlock
+
+    @classmethod
+    def _create(cls, model_class, value):
+        value = RichText(value)
+        return super()._create(model_class, value)
 
 
 class FormFieldBlockFactory(wagtail_factories.StructBlockFactory):
-    default_value = factory.Faker('word')
+    default_value = factory.Faker('sentence')
+    field_label = factory.Faker('sentence')
+    help_text = factory.LazyAttribute(lambda o: str(o._Resolver__step.builder.factory_meta.model))
 
     class Meta:
         model = stream_blocks.FormFieldBlock
@@ -138,8 +148,7 @@ class MultiFileFieldBlockFactory(UploadableMediaFactory):
 
 class StreamFieldUUIDFactory(wagtail_factories.StreamFieldFactory):
     def generate(self, step, params):
-        if not params:
-            params = self.build_form(params)
+        params = self.build_form(params)
         blocks = super().generate(step, params)
         ret_val = list()
         # Convert to JSON so we can add id before create
@@ -151,10 +160,17 @@ class StreamFieldUUIDFactory(wagtail_factories.StreamFieldFactory):
 
     def build_form(self, data):
         extras = defaultdict(dict)
+        for field, value in data.items():
+            # we dont care about position
+            name, attr = field.split('__')
+            extras[name] = {attr: value}
 
         form_fields = {}
         for i, field in enumerate(self.factories):
-            form_fields[f'{i}__{field}__'] = ''
+            if field == 'text_markup':
+                pass
+            else:
+                form_fields[f'{i}__{field}__'] = ''
             for attr, value in extras[field].items():
                 form_fields[f'{i}__{field}__{attr}'] = value
 
diff --git a/opentech/apply/utils/blocks.py b/opentech/apply/utils/blocks.py
index 3df0908995fc3a92ed3460762bafac95f9f6d24d..ee5aac70634505e766b063a2678858db0c5421ba 100644
--- a/opentech/apply/utils/blocks.py
+++ b/opentech/apply/utils/blocks.py
@@ -36,7 +36,7 @@ class RichTextFieldBlock(TextFieldBlock):
         icon = 'form'
 
     def get_searchable_content(self, value, data):
-        return bleach.clean(data, tags=[], strip=True)
+        return bleach.clean(data or '', tags=[], strip=True)
 
 
 class CustomFormFieldsBlock(StreamBlock):
diff --git a/opentech/static_src/src/sass/apply/components/_grid.scss b/opentech/static_src/src/sass/apply/components/_grid.scss
index 3a633983b84a1e8c79b415e2b3aba95347d5fb45..7756eedd427bee539deceaa5ac75a03d193ea49f 100644
--- a/opentech/static_src/src/sass/apply/components/_grid.scss
+++ b/opentech/static_src/src/sass/apply/components/_grid.scss
@@ -86,5 +86,13 @@
                 margin: 0;
             }
         }
+
+        &__cell {
+            &--span-two{
+                @include media-query(mob-landscape) {
+                    grid-column: auto / span 2;
+                }
+            }
+        }
     }
 }