diff --git a/opentech/apply/funds/tests/test_models.py b/opentech/apply/funds/tests/test_models.py
index b4e043677ce42d10b2195fdd575ec1c0f59e84b6..1d612a1e6c4bf3d3df87b05720a7dc83861a3138 100644
--- a/opentech/apply/funds/tests/test_models.py
+++ b/opentech/apply/funds/tests/test_models.py
@@ -199,9 +199,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()
 
-        data = CustomFormFieldsFactory.form_response(fields)
+        data = CustomFormFieldsFactory.form_response(page.form_fields)
 
         # Add our own data
         for field in page.forms.first().fields:
diff --git a/opentech/apply/review/forms.py b/opentech/apply/review/forms.py
index 74e1fdb150e0e450087adfd39a5ab530da185f9a..6ff588cd298bb4a9e14b66e7f497845748f97d51 100644
--- a/opentech/apply/review/forms.py
+++ b/opentech/apply/review/forms.py
@@ -3,25 +3,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 +63,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,8 +77,8 @@ 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]'))
+        for field in self.instance.score_fields:
+            value = json.loads(data.get(field.id, '[null, null]'))
 
             try:
                 score = int(value[1])
@@ -104,7 +91,4 @@ class ReviewModelForm(StreamBaseForm, forms.ModelForm, metaclass=MixedMetaClass)
         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..e038f2a94afdb06e8cb6799cec187afb6ff8faec 100644
--- a/opentech/apply/review/models.py
+++ b/opentech/apply/review/models.py
@@ -13,12 +13,48 @@ 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,
+)
+
+class ReviewFormFieldsMixin(models.Model):
+    class Meta:
+        abstract = True
 
+    form_fields = StreamField(ReviewCustomFormFieldsBlock())
 
-class ReviewForm(models.Model):
+    @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)
-    form_fields = StreamField(ReviewCustomFormFieldsBlock())
 
     panels = [
         FieldPanel('name'),
@@ -68,7 +104,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 +113,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)
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 3104760ad13d2cedb1c00cef4543c578159d40b0..9b21dcabfaaee26120e487368c872e6d9f0477ca 100644
--- a/opentech/apply/review/tests/test_views.py
+++ b/opentech/apply/review/tests/test_views.py
@@ -4,7 +4,8 @@ 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 ..options import NA
 
 
 class StaffReviewsTestCase(BaseViewTestCase):
@@ -83,24 +84,48 @@ class StaffReviewFormTestCase(BaseViewTestCase):
         self.assertEqual(response.context['title'], 'Update Review draft')
 
     def test_revision_captured_on_review(self):
-        field_ids = [f.id for f in self.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(self.submission, data, 'form')
         review = self.submission.reviews.first()
         self.assertEqual(review.revision, self.submission.live_revision)
 
     def test_can_submit_draft_review(self):
-        field_ids = [f.id for f in self.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(self.submission, data, 'form')
         review = self.submission.reviews.first()
         self.assertTrue(review.is_draft)
         self.assertIsNone(review.revision)
 
+    def test_score_calculated(self):
+        form = self.submission.round.review_forms.first()
+        score = 5
+
+        data = ReviewFormFieldsFactory.form_response(form.fields, {
+            field.id: {'score': score}
+            for field in form.form.score_fields
+        })
+
+        self.post_page(self.submission, data, 'form')
+        review = self.submission.reviews.first()
+        self.assertEqual(review.score, score)
+
+    def test_no_score_is_NA(self):
+        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)
+        self.post_page(self.submission, data, 'form')
+        review = self.submission.reviews.first()
+        self.assertEqual(review.score, NA)
+
 
 class UserReviewFormTestCase(BaseViewTestCase):
     user_factory = UserFactory
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..398a54607ebaab2b05a0c0869eee81e8c2a5509c 100644
--- a/opentech/apply/stream_forms/testing/factories.py
+++ b/opentech/apply/stream_forms/testing/factories.py
@@ -176,14 +176,19 @@ class StreamFieldUUIDFactory(wagtail_factories.StreamFieldFactory):
 
     def build_form(self, data):
         extras = defaultdict(dict)
+        exclusions = []
         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)
+            else:
+                extras[name] = {attr: value}
+
 
         form_fields = {}
         for i, field in enumerate(self.factories):
-            if field == 'text_markup':
+            if field == 'text_markup' or field in exclusions:
                 pass
             else:
                 form_fields[f'{i}__{field}__'] = ''
@@ -192,11 +197,11 @@ class StreamFieldUUIDFactory(wagtail_factories.StreamFieldFactory):
 
         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, {}))
+            for field in fields
+            if hasattr(self.factories[field.block.name], 'make_form_answer')
         }
         return flatten_for_form(data)