diff --git a/extension/reviewbotext/admin.py b/extension/reviewbotext/admin.py
index 0053f41f9019fb94f85102626ae7b342870cab17..3d965d1ab42311a1f7464d8dfbb3841d195969ed 100644
--- a/extension/reviewbotext/admin.py
+++ b/extension/reviewbotext/admin.py
@@ -7,44 +7,17 @@ from reviewboard.extensions.base import get_extension_manager
 
 from reviewbotext.extension import ReviewBotExtension
 from reviewbotext.forms import (AutomaticRunGroupForm, ManualPermissionForm,
-                                ToolForm)
+                                ToolForm, ProfileForm, ProfileFormset)
 from reviewbotext.models import (AutomaticRunGroup, ManualPermission, Profile,
                                  Tool)
 
 
 class ProfileInline(admin.StackedInline):
     model = Profile
-    # formset = ProfileFormset
-    # form = ProfileForm
+    formset = ProfileFormset
+    form = ProfileForm
     extra = 0
 
-    # fieldsets = (
-    #     ('General', {
-    #         'fields': (
-    #             'name',
-    #             'description',
-    #         ),
-    #         'classes': ('wide',),
-    #     }),
-    #     ('Execution Settings', {
-    #         'fields': (
-    #             'allow_manual',
-    #         ),
-    #         'classes': ('wide',),
-    #     }),
-    #     ('Review Settings', {
-    #         'fields': (
-    #             'ship_it',
-    #             'open_issues',
-    #             'comment_unmodified',
-    #         ),
-    #         'classes': ('wide',),
-    #     }),
-    #     (ProfileForm.TOOL_OPTIONS_FIELDSET, {
-    #         'fields': (),
-    #         'classes': ('wide',),
-    #     }),
-    # )
 
 class ToolAdmin(admin.ModelAdmin):
     inlines = [
diff --git a/extension/reviewbotext/forms.py b/extension/reviewbotext/forms.py
index e92399e325058484942f1ec61da60b605351aa80..5f59db76c5794caf76dcd2ac9d9f273db1d020d4 100644
--- a/extension/reviewbotext/forms.py
+++ b/extension/reviewbotext/forms.py
@@ -3,14 +3,13 @@ import re
 from django import forms
 from django.contrib.admin.widgets import FilteredSelectMultiple
 from django.core.exceptions import ValidationError
-from django.forms.fields import Field
-from django.forms.widgets import Widget
 from django.utils.translation import ugettext as _
 from djblets.extensions.forms import SettingsForm
 from reviewboard.scmtools.models import Repository
 
 from reviewbotext.models import (AutomaticRunGroup, ManualPermission, Profile,
                                  Tool)
+from reviewbotext.widgets import JsonDictWidget
 
 
 class ReviewBotSettingsForm(SettingsForm):
@@ -37,12 +36,25 @@ class ToolForm(forms.ModelForm):
 
 
 class ProfileFormset(forms.models.BaseInlineFormSet):
-    def __init__(self, **kwargs):
+    def __init__(self, *args, **kwargs):
         self.tool_options = kwargs.get('instance').tool_options
-        return super(ProfileFormset, self).__init__(**kwargs)
+        return super(ProfileFormset, self).__init__(*args, **kwargs)
+
+    @property
+    def empty_form(self):
+        if not hasattr(self, '_empty_form'):
+            self._empty_form = self.form(
+                auto_id=self.auto_id,
+                prefix=self.add_prefix('__prefix__'),
+                empty_permitted=True,
+                tool_options=self.tool_options)
+
+            self.add_fields(self._empty_form, None)
+
+        return self._empty_form
 
     def _construct_form(self, i, **kwargs):
-        kwargs['tool_options'] = self.tool_options
+        kwargs[u'tool_options'] = self.tool_options
         print "CONSTRUCTING A FORM"
         print kwargs
         print ""
@@ -58,7 +70,7 @@ class ProfileForm(forms.ModelForm):
     def __init__(self, *args, **kwargs):
         self.options = kwargs.pop('tool_options', None)
         super(ProfileForm, self).__init__(*args, **kwargs)
-        self.tool_opt_form = None
+        # self.tool_opt_form = None
 
         if self.options is None:
             return
@@ -70,109 +82,28 @@ class ProfileForm(forms.ModelForm):
         if instance:
             settings = instance.tool_settings
 
-        form_class = self._make_tool_opt_form(options, settings)
-        self.tool_opt_form = form_class(self.data or None)
-
-    def is_valid(self):
-        """Returns whether or not the form is valid."""
-        return (super(ProfileForm, self).is_valid() and
-                self.tool_opt_form.is_valid())
-
-    def save(self, commit=True, *args, **kwargs):
-        tool_profile = super(ProfileForm, self).save(commit=False,
-                                                         *args, **kwargs)
-
-        # options = tool_profile.tool_options
-        options = self.options
-        settings = tool_profile.tool_settings
-
-        for option in options:
-            print option
-            field_name = option['name']
-            settings[field_name] = self.tool_opt_form.cleaned_data[field_name]
-
-        tool_profile.tool_settings = settings
-
-        if commit:
-            tool_profile.save()
-
-        return tool_profile
-
-
-    def _make_tool_opt_form(self, options, settings):
-        """Construct the tool specific settings form.
-
-        Given the tool's tool_options, and tool_settings
-        construct a new form class with the proper fields.
-        """
-        fields = {}
-
-        for option in options:
-            field_name = option['name']
-            field_class = self._get_field_class(option['field_type'])
-
-            # If this field specifies which widget it wants to use, we must
-            # instantiate the widget and pass it to the field constructor.
-            widget = option.get('widget', None)
-
-            if widget is not None:
-                widget_class = self._get_widget_class(widget['type'])
-
-                widget_attrs = widget.get('attrs', None)
-                widget = widget_class(attrs=widget_attrs)
-
-            field_options = option.get('field_options', {})
-            option_value = settings.get(field_name, None)
-
-            if option_value is not None:
-                field_options['initial'] = option_value
-
-            # Note: We pass the widget separately instead of including it in
-            # field_options because field_options must be serializable.
-            # (field_options is referenced by the tool's actual tool_options
-            # JSON field.)
-            fields[field_name] = field_class(widget=widget, **field_options)
-
-        return type('ReviewBotToolOptionsForm', (forms.Form,), fields)
-
-    def _get_field_class(self, class_str):
-        """Import and return the field class.
-
-        Given the module path to a field class in class_str, imports the class
-        and returns it. If class_str does not specify a valid field class, an
-        exception is raised.
-        """
-        field_class = self._get_class(class_str)
-
-        if not issubclass(field_class, Field):
-            raise TypeError('%s is not a Field class.' % class_str)
-
-        return field_class
-
-    def _get_widget_class(self, widget_str):
-        """Imports and returns the widget class.
-
-        If widget_str does not specify a valid widget class, an exception is
-        raised.
-        """
-        widget_class = self._get_class(widget_str)
+        self.fields['tool_settings'] = self._make_tool_settings_field(
+            options,
+            settings)
 
-        if not issubclass(widget_class, Widget):
-            raise TypeError('%s is not a Widget class.' % widget_str)
+    def _get_model_field(self, name):
+        """Get model's field of given name."""
+        for field in self._meta.model._meta.fields:
+            if field.name is name:
+                return field
 
-        return widget_class
+        return None
 
-    def _get_class(self, class_str):
-        """Imports and returns the class, given the module path to a class."""
-        class_path = str(class_str).split('.')
+    def _make_tool_settings_field_widget(self, options, settings):
+        """Make widget for tool_settings formfield"""
+        return JsonDictWidget(options)
 
-        if len(class_path) > 1:
-            module_name = '.'.join(class_path[:-1])
-        else:
-            module_name = '.'
+    def _make_tool_settings_field(self, options, settings):
+        """Make tool_settings formfield"""
+        widget = self._make_tool_settings_field_widget(options, settings)
+        field = self._get_model_field('tool_settings')
 
-        module = __import__(module_name, {}, {}, class_path[-1])
-        return getattr(module, class_path[-1])
+        return field.formfield(widget=widget)
 
 
 def _regex_validator(regex):
diff --git a/extension/reviewbotext/utils.py b/extension/reviewbotext/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..6520372c580680ae7c66976e73d74b3c7e04fa55
--- /dev/null
+++ b/extension/reviewbotext/utils.py
@@ -0,0 +1,13 @@
+def get_class(class_str):
+    """Imports and returns the class, given the module path to a class."""
+    class_path = str(class_str).split('.')
+
+    if class_path:
+        module_name = '.'.join(class_path[:-1])
+    else:
+        module_name = '.'
+
+    module = __import__(module_name, {}, {}, class_path[-1])
+    ret = getattr(module, class_path[-1])
+
+    return ret
diff --git a/extension/reviewbotext/widgets.py b/extension/reviewbotext/widgets.py
new file mode 100644
index 0000000000000000000000000000000000000000..d731b751530f238ef26ef277a48623ff04c02b61
--- /dev/null
+++ b/extension/reviewbotext/widgets.py
@@ -0,0 +1,100 @@
+import json
+
+from django.forms.widgets import MultiWidget
+from django.utils.six.moves import zip
+
+from reviewbotext.utils import get_class
+
+
+class JsonDictWidget(MultiWidget):
+    """Widget for JSONField.
+
+    This widget is for a JSONField with pre-defiend keys and value-types.
+    """
+
+    def __init__(self, raw_field_data_arr, attrs=None):
+        self.field_data_arr = self._make_field_data_arr(raw_field_data_arr)
+
+        super(JsonDictWidget, self).__init__(
+            self._get_widgets(),
+            attrs)
+
+    def _get_widgets(self):
+        """Get the list of widgets in this object."""
+        return [field.widget for field in self._get_fields()]
+
+    def _get_fields(self):
+        """Get the list of fields in this object."""
+        return [field_data['field'] for field_data in self.field_data_arr]
+
+    def _make_field_data_arr(self, raw_data_arr):
+        """Make field data array using raw data arr."""
+        return [self._make_field_data(raw_data) for raw_data in raw_data_arr]
+
+    def _make_field_data(self, raw_data):
+        """Make field data using raw data."""
+        return {
+            'name': raw_data['name'],
+            'default': raw_data.get('default', None),
+            'options': raw_data['field_options'],
+            'field': self._make_field(raw_data)
+        }
+
+    def _make_widget(self, widget_data):
+        """Make field data using raw data."""
+        if widget_data is None:
+            return None
+
+        widget_class = get_class(widget_data['type'])
+        widget_attrs = widget_data.get('attrs', None)
+
+        return widget_class(attrs=widget_attrs)
+
+    def _make_field(self, raw_data):
+        """Make field(form field) using raw data."""
+        field_class = get_class(raw_data['field_type'])
+        field_options = raw_data.get('field_options', {})
+        widget = self._make_widget(raw_data.get('widget', None))
+
+        return field_class(widget=widget, **field_options)
+
+    def format_output(self, rendered_widgets):
+        """Return html formatted output of this widget."""
+        row_template = (
+            '<div class="field-row">'
+            '    <label class="key">%s:</label>'
+            '    %s'
+            '</div>'
+        )
+
+        pair_arr = zip(self.field_data_arr, rendered_widgets)
+
+        div_contents = (
+            row_template % (field_data['options']['label'], rendered_widget)
+            for (field_data, rendered_widget) in pair_arr)
+
+        return '<fieldset class="json-dict">%s</fieldset>' % (
+            "".join(div_contents))
+
+    def decompress(self, value):
+        """Return array of values, given value of the field of this widget."""
+        value_dict = json.loads(value) or {}
+
+        return [
+            value_dict.get(field_data['name'], field_data['default'])
+            for field_data in self.field_data_arr
+        ]
+
+    def value_from_datadict(self, data, files, name):
+        """Return value of the field of this widget, given array of data."""
+        value_arr = (
+            widget.value_from_datadict(data, files, name + '_%s' % i)
+            for i, widget in enumerate(self.widgets)
+        )
+
+        ret = dict(
+            (field_data['name'], value)
+            for (field_data, value) in zip(self.field_data_arr, value_arr)
+        )
+
+        return json.dumps(ret)
