diff --git a/opentech/apply/funds/models/mixins.py b/opentech/apply/funds/models/mixins.py
index 50c3c0ccdb24e4e3d3e68df66a36c8260cdb2aba..fbc9a879df0c28d2c803ac1e566a257edeb5d529 100644
--- a/opentech/apply/funds/models/mixins.py
+++ b/opentech/apply/funds/models/mixins.py
@@ -22,33 +22,27 @@ class AccessFormData:
         # 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
+            if field_id not in data:
+                response = data[field_name]
+                data[field_id] = response
         return data
 
+    def get_definitive_id(self, id):
+        if id in self.must_include:
+            return self.must_include[id]
+        return id
+
     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]
+        definitive_id = self.get_definitive_id(id)
+        return self.raw_fields[definitive_id]
 
     def data(self, id):
+        definitive_id = self.get_definitive_id(id)
         try:
-            return self.form_data[id]
+            return self.raw_data[definitive_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]
+            # We have most likely progressed application forms so the data isnt in form_data
+            return None
 
     @property
     def question_field_ids(self):
diff --git a/opentech/apply/funds/templates/funds/includes/review_table.html b/opentech/apply/funds/templates/funds/includes/review_table.html
index 795f47c1ad60a13add873f991a8fcd9a05def0f0..cacd82ba33e77deae9332d836e639a98d5aa2ef6 100644
--- a/opentech/apply/funds/templates/funds/includes/review_table.html
+++ b/opentech/apply/funds/templates/funds/includes/review_table.html
@@ -5,7 +5,7 @@
             <tr class="tr tr--subchild light-grey-bg">
                 <th colspan="2"></th>
                 <th>{{ object.reviews.submitted.recommendation|traffic_light }}</th>
-                <th>{{ object.reviews.submitted.score|floatformat|default_if_none:'-' }}</th>
+                <th>{{ object.reviews.submitted.get_score_display|default_if_none:'-' }}</th>
             </tr>
             {% include 'funds/includes/review_table_row.html' with reviews=staff_reviews %}
         {% endif %}
diff --git a/opentech/apply/funds/templates/funds/includes/review_table_row.html b/opentech/apply/funds/templates/funds/includes/review_table_row.html
index 18b05f47d4f41642624e0b0f7a62a125b01d2572..1717b7fe71c31cdddef0e56d00e2bb34e692dccb 100644
--- a/opentech/apply/funds/templates/funds/includes/review_table_row.html
+++ b/opentech/apply/funds/templates/funds/includes/review_table_row.html
@@ -6,7 +6,7 @@
             <td>-</td>
         {% else %}
             <td class="reviews-sidebar__author" colspan="2">
-                {% if request.user.is_apply_staff %}
+                {% if request.user.is_apply_staff or request.user == review.author %}
                     <a href="{% url 'apply:submissions:reviews:review' submission_pk=review.submission.id pk=review.id %}">
                         <span>{{ review.author }}</span>
                     </a>
diff --git a/opentech/apply/funds/tests/test_models.py b/opentech/apply/funds/tests/test_models.py
index 32389220da12b4abd0df8e937c299bc889a3ecb0..10e29363d5bccd2bfc70ba47f2fadb94e7dfe6d8 100644
--- a/opentech/apply/funds/tests/test_models.py
+++ b/opentech/apply/funds/tests/test_models.py
@@ -195,8 +195,8 @@ class TestFormSubmission(TestCase):
 
     def submit_form(self, page=None, email=None, name=None, user=AnonymousUser(), ignore_errors=False):
         page = page or self.round_page
-        fields = page.get_form_fields()
 
+        fields = page.forms.first().fields
         data = CustomFormFieldsFactory.form_response(fields)
 
         # Add our own data
diff --git a/opentech/apply/review/blocks.py b/opentech/apply/review/blocks.py
index d271c864c1b8a5649b31804c35aebd3c8fb5bb97..6398ae8c14f649c4824521d4e2f624928cfb32e7 100644
--- a/opentech/apply/review/blocks.py
+++ b/opentech/apply/review/blocks.py
@@ -22,7 +22,11 @@ class ScoreFieldBlock(OptionalFormFieldBlock):
         template = 'review/render_scored_answer_field.html'
 
     def render(self, value, context=None):
-        comment, score = json.loads(context['data'])
+        try:
+            comment, score = context['data']
+        except ValueError:
+            # TODO: Remove json load as data moved away from JSON
+            comment, score = json.loads(context['data'])
         context.update(**{
             'comment': comment,
             'score': RATE_CHOICES_DICT.get(int(score), RATE_CHOICE_NA)
diff --git a/opentech/apply/review/fields.py b/opentech/apply/review/fields.py
index aeaeaa79eb517c85006e86140f7eb216f9536836..169ca4bd95ea2a416d72f222c259194bb9e69022 100644
--- a/opentech/apply/review/fields.py
+++ b/opentech/apply/review/fields.py
@@ -1,12 +1,10 @@
-import json
-
 from django import forms
 from tinymce import TinyMCE
 
 from django.forms import widgets
 from django.utils.safestring import mark_safe
 
-from opentech.apply.review.options import RATE_CHOICES
+from opentech.apply.review.options import RATE_CHOICES, NA
 from opentech.apply.utils.options import MCE_ATTRIBUTES_SHORT
 
 
@@ -19,44 +17,22 @@ class ScoredAnswerWidget(forms.MultiWidget):
         super().__init__(_widgets, attrs)
 
     def decompress(self, value):
+        # We should only hit this on initialisation where we set the default to a list of None
         if value:
-            return json.loads(value)
+            return value
         return [None, None]
 
     def render(self, name, value, attrs=None, renderer=None):
-        """
-        Render the widget as an HTML string.
-        Required for the correct rendering of the TinyMCE widget.
-        """
-        if self.is_localized:
-            for widget in self.widgets:
-                widget.is_localized = self.is_localized
-        # value is a list of values, each corresponding to a widget
-        # in self.widgets.
-        if not isinstance(value, list):
-            value = self.decompress(value)
-
+        context = self.get_context(name, value, attrs)
         rendered = []
-        final_attrs = self.build_attrs(attrs)
-        input_type = final_attrs.pop('type', None)
-        id_ = final_attrs.get('id')
-        for i, widget in enumerate(self.widgets):
-            if input_type is not None:
-                widget.input_type = input_type
-            widget_name = '%s_%s' % (name, i)
-            try:
-                widget_value = value[i]
-            except IndexError:
-                widget_value = None
-            if id_:
-                widget_attrs = final_attrs.copy()
-                widget_attrs['id'] = '%s_%s' % (id_, i)
-            else:
-                widget_attrs = final_attrs
-
-            rendered.append(widget.render(widget_name, widget_value, widget_attrs, renderer))
-
-        return ''.join([mark_safe(item) for item in rendered])
+        # We need to explicitly call the render method on the tinymce widget
+        # MultiValueWidget just passes all the context into the template
+        for kwargs, widget in zip(context['widget']['subwidgets'], self.widgets):
+            name = kwargs['name']
+            value = kwargs['value']
+            attrs = kwargs['attrs']
+            rendered.append(widget.render(name, value, attrs, renderer))
+        return mark_safe(''.join([widget for widget in rendered]))
 
 
 class ScoredAnswerField(forms.MultiValueField):
@@ -71,4 +47,7 @@ class ScoredAnswerField(forms.MultiValueField):
         super().__init__(fields=fields, *args, **kwargs)
 
     def compress(self, data_list):
-        return json.dumps(data_list)
+        if data_list:
+            return [data_list[0], int(data_list[1])]
+        else:
+            return ['', NA]
diff --git a/opentech/apply/review/forms.py b/opentech/apply/review/forms.py
index 74e1fdb150e0e450087adfd39a5ab530da185f9a..51a5f298d7391f93bf271f294ace0a03cbe8a14e 100644
--- a/opentech/apply/review/forms.py
+++ b/opentech/apply/review/forms.py
@@ -1,27 +1,12 @@
-import json
-
 from django import forms
 from django.core.exceptions import NON_FIELD_ERRORS
 
-from opentech.apply.review.blocks import ScoredAnswerField
 from opentech.apply.review.options import NA
 from opentech.apply.stream_forms.forms import StreamBaseForm
 
-from .blocks import RecommendationBlock
 from .models import Review
 
 
-def get_recommendation_field(fields):
-    for field in fields:
-        try:
-            block = field.block
-        except AttributeError:
-            pass
-        else:
-            if isinstance(block, RecommendationBlock):
-                return field.id
-
-
 class MixedMetaClass(type(StreamBaseForm), type(forms.ModelForm)):
     pass
 
@@ -76,7 +61,7 @@ class ReviewModelForm(StreamBaseForm, forms.ModelForm, metaclass=MixedMetaClass)
 
     def save(self, commit=True):
         self.instance.score = self.calculate_score(self.cleaned_data)
-        self.instance.recommendation = int(self.cleaned_data[get_recommendation_field(self.instance.form_fields)])
+        self.instance.recommendation = int(self.cleaned_data[self.instance.reccomendation_field.id])
         self.instance.is_draft = self.draft_button_name in self.data
 
         self.instance.form_data = self.cleaned_data['form_data']
@@ -90,21 +75,12 @@ class ReviewModelForm(StreamBaseForm, forms.ModelForm, metaclass=MixedMetaClass)
     def calculate_score(self, data):
         scores = list()
 
-        for field in self.get_score_fields():
-            value = json.loads(data.get(field, '[null, null]'))
-
-            try:
-                score = int(value[1])
-            except TypeError:
-                pass
-            else:
-                if score != NA:
-                    scores.append(score)
+        for field in self.instance.score_fields:
+            score = data.get(field.id)[1]
+            if score != NA:
+                scores.append(score)
 
         try:
             return sum(scores) / len(scores)
         except ZeroDivisionError:
-            return 0
-
-    def get_score_fields(self):
-        return [field_name for field_name, field in self.fields.items() if isinstance(field, ScoredAnswerField)]
+            return NA
diff --git a/opentech/apply/review/models.py b/opentech/apply/review/models.py
index fff92008729805052d55e0e07e1fa2b8e1fbe176..c47a65c0d16a734a6dbe666607c18dc13a2d8b68 100644
--- a/opentech/apply/review/models.py
+++ b/opentech/apply/review/models.py
@@ -13,13 +13,51 @@ from opentech.apply.review.options import YES, NO, MAYBE, RECOMMENDATION_CHOICES
 from opentech.apply.stream_forms.models import BaseStreamForm
 from opentech.apply.users.models import User
 
-from .blocks import ReviewCustomFormFieldsBlock
+from .blocks import (
+    ReviewCustomFormFieldsBlock,
+    RecommendationBlock,
+    RecommendationCommentsBlock,
+    ScoreFieldBlock,
+)
+from .options import NA
 
 
-class ReviewForm(models.Model):
-    name = models.CharField(max_length=255)
+class ReviewFormFieldsMixin(models.Model):
+    class Meta:
+        abstract = True
+
     form_fields = StreamField(ReviewCustomFormFieldsBlock())
 
+    @property
+    def score_fields(self):
+        return self._get_field_type(ScoreFieldBlock, many=True)
+
+    @property
+    def reccomendation_field(self):
+        return self._get_field_type(RecommendationBlock)
+
+    @property
+    def comment_field(self):
+        return self._get_field_type(RecommendationCommentsBlock)
+
+    def _get_field_type(self, block_type, many=False):
+        fields = list()
+        for field in self.form_fields:
+            try:
+                if isinstance(field.block, block_type):
+                    if many:
+                        fields.append(field)
+                    else:
+                        return field
+            except AttributeError:
+                pass
+        if many:
+            return fields
+
+
+class ReviewForm(ReviewFormFieldsMixin, models.Model):
+    name = models.CharField(max_length=255)
+
     panels = [
         FieldPanel('name'),
         StreamFieldPanel('form_fields'),
@@ -52,7 +90,7 @@ class ReviewQuerySet(models.QuerySet):
         return self.by_reviewers().recommendation()
 
     def score(self):
-        return self.aggregate(models.Avg('score'))['score__avg']
+        return self.exclude(score=NA).aggregate(models.Avg('score'))['score__avg']
 
     def recommendation(self):
         recommendations = self.values_list('recommendation', flat=True)
@@ -68,7 +106,7 @@ class ReviewQuerySet(models.QuerySet):
             return MAYBE
 
 
-class Review(BaseStreamForm, AccessFormData, models.Model):
+class Review(ReviewFormFieldsMixin, BaseStreamForm, AccessFormData, models.Model):
     submission = models.ForeignKey('funds.ApplicationSubmission', on_delete=models.CASCADE, related_name='reviews')
     revision = models.ForeignKey('funds.ApplicationRevision', on_delete=models.SET_NULL, related_name='reviews', null=True)
     author = models.ForeignKey(
@@ -77,7 +115,6 @@ class Review(BaseStreamForm, AccessFormData, models.Model):
     )
 
     form_data = JSONField(default=dict, encoder=DjangoJSONEncoder)
-    form_fields = StreamField(ReviewCustomFormFieldsBlock())
 
     recommendation = models.IntegerField(verbose_name="Recommendation", choices=RECOMMENDATION_CHOICES, default=0)
     score = models.DecimalField(max_digits=10, decimal_places=1, default=0)
@@ -92,6 +129,12 @@ class Review(BaseStreamForm, AccessFormData, models.Model):
     def outcome(self):
         return self.get_recommendation_display()
 
+    def get_comments_display(self, include_question=True):
+        return self.render_answer(self.comment_field.id, include_question=include_question)
+
+    def get_score_display(self):
+        return '{:.1f}'.format(self.score) if self.score != NA else 'NA'
+
     def get_absolute_url(self):
         return reverse('apply:reviews:review', args=(self.id,))
 
diff --git a/opentech/apply/review/templates/review/review_detail.html b/opentech/apply/review/templates/review/review_detail.html
index 94182ff8fd81de68d0d9ea6f031010f4b77fb86c..8581f9d77c2c74931bbd6865501b5d6f935ff1c8 100644
--- a/opentech/apply/review/templates/review/review_detail.html
+++ b/opentech/apply/review/templates/review/review_detail.html
@@ -29,6 +29,8 @@
 </div>
 
 <div class="rich-text rich-text--answers">
+    {{ object.get_comments_display }}
+
     {{ object.output_answers }}
 </div>
 {% endblock %}
diff --git a/opentech/apply/review/tests/factories/blocks.py b/opentech/apply/review/tests/factories/blocks.py
index 82cd4a011bddef0e86086bd13b114caa92b1d9d9..31d6290a9dd01a88fdffd2cc908d7733fc926e0f 100644
--- a/opentech/apply/review/tests/factories/blocks.py
+++ b/opentech/apply/review/tests/factories/blocks.py
@@ -35,10 +35,12 @@ class ScoreFieldBlockFactory(FormFieldBlockFactory):
 
     @classmethod
     def make_form_answer(cls, params=dict()):
-        return {
-            'description': factory.Faker('paragraph').generate(params),
+        defaults = {
+            'description': factory.Faker('paragraph').generate({}),
             'score': random.randint(1, 5),
         }
+        defaults.update(params)
+        return defaults
 
 
 ReviewFormFieldsFactory = StreamFieldUUIDFactory({
diff --git a/opentech/apply/review/tests/test_views.py b/opentech/apply/review/tests/test_views.py
index 91dd7202dba7302aa274636ecfd9161eeb87d288..682500b50994cdd428969f42690d3ef1b12dce19 100644
--- a/opentech/apply/review/tests/test_views.py
+++ b/opentech/apply/review/tests/test_views.py
@@ -4,7 +4,9 @@ from opentech.apply.funds.tests.factories.models import ApplicationSubmissionFac
 from opentech.apply.users.tests.factories import StaffFactory, UserFactory
 from opentech.apply.utils.testing.tests import BaseViewTestCase
 
-from .factories import ReviewFactory, ReviewFormFieldsFactory
+from .factories import ReviewFactory, ReviewFormFieldsFactory, ReviewFormFactory
+from ..models import Review
+from ..options import NA
 
 
 class StaffReviewsTestCase(BaseViewTestCase):
@@ -46,20 +48,32 @@ class StaffReviewListingTestCase(BaseViewTestCase):
         for review in reviews:
             self.assertContains(response, review.author.full_name)
 
+    def test_draft_reviews_dont_appear(self):
+        submission = ApplicationSubmissionFactory()
+        review = ReviewFactory.create(submission=submission, is_draft=True)
+        response = self.get_page(submission, 'list')
+        self.assertContains(response, submission.title)
+        self.assertContains(response, reverse('funds:submissions:detail', kwargs={'pk': submission.id}))
+        self.assertNotContains(response, review.author.full_name)
+
 
 class StaffReviewFormTestCase(BaseViewTestCase):
     user_factory = StaffFactory
     url_name = 'funds:submissions:reviews:{}'
     base_view_name = 'review'
 
+    @classmethod
+    def setUpTestData(cls):
+        super().setUpTestData()
+        cls.submission = ApplicationSubmissionFactory(status='internal_review')
+
     def get_kwargs(self, instance):
         return {'submission_pk': instance.id}
 
     def test_can_access_form(self):
-        submission = ApplicationSubmissionFactory(status='internal_review')
-        response = self.get_page(submission, 'form')
-        self.assertContains(response, submission.title)
-        self.assertContains(response, reverse('funds:submissions:detail', kwargs={'pk': submission.id}))
+        response = self.get_page(self.submission, 'form')
+        self.assertContains(response, self.submission.title)
+        self.assertContains(response, reverse('funds:submissions:detail', kwargs={'pk': self.submission.id}))
 
     def test_cant_access_wrong_status(self):
         submission = ApplicationSubmissionFactory(rejected=True)
@@ -67,41 +81,103 @@ class StaffReviewFormTestCase(BaseViewTestCase):
         self.assertEqual(response.status_code, 403)
 
     def test_cant_resubmit_review(self):
-        submission = ApplicationSubmissionFactory(status='internal_review')
-        ReviewFactory(submission=submission, author=self.user)
-        response = self.post_page(submission, {'data': 'value'}, 'form')
+        ReviewFactory(submission=self.submission, author=self.user)
+        response = self.post_page(self.submission, {'data': 'value'}, 'form')
         self.assertEqual(response.context['has_submitted_review'], True)
         self.assertEqual(response.context['title'], 'Update Review draft')
 
     def test_can_edit_draft_review(self):
-        submission = ApplicationSubmissionFactory(status='internal_review')
-        ReviewFactory(submission=submission, author=self.user, is_draft=True)
-        response = self.post_page(submission, {'data': 'value'}, 'form')
+        ReviewFactory(submission=self.submission, author=self.user, is_draft=True)
+        response = self.get_page(self.submission, 'form')
         self.assertEqual(response.context['has_submitted_review'], False)
         self.assertEqual(response.context['title'], 'Update Review draft')
 
     def test_revision_captured_on_review(self):
-        submission = ApplicationSubmissionFactory(status='internal_review')
-        field_ids = [f.id for f in submission.round.review_forms.first().fields]
+        form = self.submission.round.review_forms.first()
 
-        data = ReviewFormFieldsFactory.form_response(field_ids)
+        data = ReviewFormFieldsFactory.form_response(form.fields)
 
-        self.post_page(submission, data, 'form')
-        review = submission.reviews.first()
-        self.assertEqual(review.revision, submission.live_revision)
+        self.post_page(self.submission, data, 'form')
+        review = self.submission.reviews.first()
+        self.assertEqual(review.revision, self.submission.live_revision)
 
     def test_can_submit_draft_review(self):
-        submission = ApplicationSubmissionFactory(status='internal_review')
-        field_ids = [f.id for f in submission.round.review_forms.first().fields]
+        form = self.submission.round.review_forms.first()
 
-        data = ReviewFormFieldsFactory.form_response(field_ids)
+        data = ReviewFormFieldsFactory.form_response(form.fields)
         data['save_draft'] = True
-        self.post_page(submission, data, 'form')
-        review = submission.reviews.first()
+        self.post_page(self.submission, data, 'form')
+        review = self.submission.reviews.first()
         self.assertTrue(review.is_draft)
         self.assertIsNone(review.revision)
 
 
+class TestReviewScore(BaseViewTestCase):
+    user_factory = StaffFactory
+    url_name = 'funds:submissions:reviews:{}'
+    base_view_name = 'review'
+
+    @classmethod
+    def setUpTestData(cls):
+        super().setUpTestData()
+        cls.submission = ApplicationSubmissionFactory(status='internal_review')
+
+    def get_kwargs(self, instance):
+        return {'submission_pk': instance.id}
+
+    def submit_review_scores(self, *scores):
+        if scores:
+            form = ReviewFormFactory(form_fields__multiple__score=len(scores))
+        else:
+            form = ReviewFormFactory(form_fields__exclude__score=True)
+        review_form = self.submission.round.review_forms.first()
+        review_form.form = form
+        review_form.save()
+
+        data = ReviewFormFieldsFactory.form_response(form.form_fields, {
+            field.id: {'score': score}
+            for field, score in zip(form.score_fields, scores)
+        })
+
+        # Make a new person for every review
+        self.client.force_login(self.user_factory())
+        response = self.post_page(self.submission, data, 'form')
+        self.assertIn(
+            'funds/applicationsubmission_admin_detail.html',
+            response.template_name,
+            msg='Failed to post the form correctly'
+        )
+        self.client.force_login(self.user)
+        return self.submission.reviews.first()
+
+    def test_score_calculated(self):
+        review = self.submit_review_scores(5)
+        self.assertEqual(review.score, 5)
+
+    def test_average_score_calculated(self):
+        review = self.submit_review_scores(1, 5)
+        self.assertEqual(review.score, (1 + 5) / 2)
+
+    def test_no_score_is_NA(self):
+        review = self.submit_review_scores()
+        self.assertEqual(review.score, NA)
+
+    def test_na_not_included_in_review_average(self):
+        review = self.submit_review_scores(NA, 5)
+        self.assertEqual(review.score, 5)
+
+    def test_na_not_included_reviews_average(self):
+        self.submit_review_scores(NA)
+        self.assertIsNone(Review.objects.score())
+
+    def test_na_not_included_multiple_reviews_average(self):
+        self.submit_review_scores(NA)
+        self.submit_review_scores(5)
+
+        self.assertEqual(Review.objects.count(), 2)
+        self.assertEqual(Review.objects.score(), 5)
+
+
 class UserReviewFormTestCase(BaseViewTestCase):
     user_factory = UserFactory
     url_name = 'funds:submissions:reviews:{}'
diff --git a/opentech/apply/review/views.py b/opentech/apply/review/views.py
index 08f7838455ade3596759823f30bd9a760545a5e1..cc98a147e48782e65de43a0eb1eba483260ae0f4 100644
--- a/opentech/apply/review/views.py
+++ b/opentech/apply/review/views.py
@@ -9,7 +9,7 @@ from wagtail.core.blocks import RichTextBlock
 
 from opentech.apply.activity.messaging import messenger, MESSAGES
 from opentech.apply.funds.models import ApplicationSubmission
-from opentech.apply.review.blocks import RecommendationBlock
+from opentech.apply.review.blocks import RecommendationBlock, RecommendationCommentsBlock
 from opentech.apply.review.forms import ReviewModelForm
 from opentech.apply.stream_forms.models import BaseStreamForm
 from opentech.apply.users.decorators import staff_required
@@ -119,9 +119,12 @@ class ReviewListView(ListView):
 
     def get_queryset(self):
         self.submission = get_object_or_404(ApplicationSubmission, id=self.kwargs['submission_pk'])
-        self.queryset = self.model.objects.filter(submission=self.submission)
+        self.queryset = self.model.objects.filter(submission=self.submission, is_draft=False)
         return super().get_queryset()
 
+    def should_display(self, field):
+        return not isinstance(field.block, (RecommendationBlock, RecommendationCommentsBlock, RichTextBlock))
+
     def get_context_data(self, **kwargs):
         review_data = {}
 
@@ -130,13 +133,15 @@ class ReviewListView(ListView):
         review_data['score'] = {'question': 'Overall Score', 'answers': list()}
         review_data['recommendation'] = {'question': 'Recommendation', 'answers': list()}
         review_data['revision'] = {'question': 'Revision', 'answers': list()}
+        review_data['comments'] = {'question': 'Comments', 'answers': list()}
 
         responses = self.object_list.count()
 
         for i, review in enumerate(self.object_list):
             review_data['title']['answers'].append(str(review.author))
-            review_data['score']['answers'].append(str(review.score))
+            review_data['score']['answers'].append(str(review.get_score_display()))
             review_data['recommendation']['answers'].append(review.get_recommendation_display())
+            review_data['comments']['answers'].append(review.get_comments_display(include_question=False))
             if review.for_latest:
                 revision = 'Current'
             else:
@@ -146,7 +151,7 @@ class ReviewListView(ListView):
             for field_id in review.fields:
                 field = review.field(field_id)
                 data = review.data(field_id)
-                if not isinstance(field.block, (RecommendationBlock, RichTextBlock)):
+                if self.should_display(field):
                     question = field.value['field_label']
                     review_data.setdefault(field.id, {'question': question, 'answers': [''] * responses})
                     review_data[field.id]['answers'][i] = field.block.render(None, {'data': data})
diff --git a/opentech/apply/stream_forms/blocks.py b/opentech/apply/stream_forms/blocks.py
index 0b850540c8f7008057098a7899d3ccdb6fdd52b3..117192eebe74114ebb19e9dcff4e67bbd5870215 100644
--- a/opentech/apply/stream_forms/blocks.py
+++ b/opentech/apply/stream_forms/blocks.py
@@ -47,8 +47,8 @@ class FormFieldBlock(StructBlock):
         return kwargs
 
     def get_field(self, struct_value):
-        return self.get_field_class(struct_value)(
-            **self.get_field_kwargs(struct_value))
+        field_kwargs = self.get_field_kwargs(struct_value)
+        return self.get_field_class(struct_value)(**field_kwargs)
 
     def get_context(self, value, parent_context):
         context = super().get_context(value, parent_context)
diff --git a/opentech/apply/stream_forms/testing/factories.py b/opentech/apply/stream_forms/testing/factories.py
index fb7630a07135dcfbf24786cab258727a49d1257f..f742d6c50628280aacbf96197134fb594abe6566 100644
--- a/opentech/apply/stream_forms/testing/factories.py
+++ b/opentech/apply/stream_forms/testing/factories.py
@@ -176,27 +176,43 @@ class StreamFieldUUIDFactory(wagtail_factories.StreamFieldFactory):
 
     def build_form(self, data):
         extras = defaultdict(dict)
+        exclusions = []
+        multiples = dict()
         for field, value in data.items():
             # we dont care about position
             name, attr = field.split('__')
-            extras[name] = {attr: value}
+            if name == 'exclude':
+                exclusions.append(attr)
+            elif name == 'multiple':
+                multiples[attr] = value
+            else:
+                extras[name] = {attr: value}
+
+        defined_both = set(exclusions) & set(multiples)
+        if defined_both:
+            raise ValueError(
+                'Cant exclude and provide multiple at the same time: {}'.format(', '.join(defined_both))
+            )
 
         form_fields = {}
-        for i, field in enumerate(self.factories):
-            if field == 'text_markup':
+        field_count = 0
+        for field in self.factories:
+            if field == 'text_markup' or field in exclusions:
                 pass
             else:
-                form_fields[f'{i}__{field}__'] = ''
+                for _ in range(multiples.get(field, 1)):
+                    form_fields[f'{field_count}__{field}__'] = ''
+                    field_count += 1
             for attr, value in extras[field].items():
-                form_fields[f'{i}__{field}__{attr}'] = value
+                form_fields[f'{field_count}__{field}__{attr}'] = value
 
         return form_fields
 
-    def form_response(self, fields):
+    def form_response(self, fields, field_values=dict()):
         data = {
-            field: factory.make_form_answer()
-            for field, factory in zip(fields, self.factories.values())
-            if hasattr(factory, 'make_form_answer')
+            field.id: self.factories[field.block.name].make_form_answer(field_values.get(field.id, {}))
+            for field in fields
+            if hasattr(self.factories[field.block.name], 'make_form_answer')
         }
         return flatten_for_form(data)