diff --git a/smash/web/forms.py b/smash/web/forms.py
index 0c062b1afd94b821ddb37abf7e28aa7bff2e53ec..2b50d8ba57e22de782dde8cbb113038cb629c391 100644
--- a/smash/web/forms.py
+++ b/smash/web/forms.py
@@ -1,11 +1,13 @@
 import datetime
 import logging
+import re
 from collections import OrderedDict
 
 from django import forms
 from django.forms import ModelForm, Form
 from django.utils.dates import MONTHS
 
+from models import Study, StudyColumns
 from web.models import Subject, StudySubject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, \
     AppointmentTypeLink, \
     Availability, Holiday
@@ -41,11 +43,16 @@ logger = logging.getLogger(__name__)
 
 
 def validate_subject_nd_number(self, cleaned_data):
-    if cleaned_data['nd_number'] != "":
-        subjects_from_db = StudySubject.objects.filter(nd_number=cleaned_data['nd_number'])
-        if subjects_from_db:
-            if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
-                self.add_error('nd_number', "ND number already in use")
+    if self.study.columns.nd_number:
+        nd_number = cleaned_data['nd_number']
+        if nd_number != "":
+            if re.match('ND[0-9][0-9][0-9][0-9]', nd_number) is None:
+                self.add_error('nd_number', "Invalid ND number")
+            else:
+                subjects_from_db = StudySubject.objects.filter(nd_number=nd_number, study=self.study)
+                if subjects_from_db:
+                    if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
+                        self.add_error('nd_number', "ND number already in use")
 
 
 def validate_subject_country(self, cleaned_data):
@@ -59,11 +66,12 @@ def validate_subject_resign_reason(self, cleaned_data):
 
 
 def validate_subject_mpower_number(self, cleaned_data):
-    if cleaned_data['mpower_id'] != "":
-        subjects_from_db = StudySubject.objects.filter(mpower_id=cleaned_data['mpower_id'])
-        if subjects_from_db:
-            if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
-                self.add_error('mpower_id', "mPower number already in use")
+    if self.study.columns.mpower_id:
+        if cleaned_data['mpower_id'] != "":
+            subjects_from_db = StudySubject.objects.filter(mpower_id=cleaned_data['mpower_id'])
+            if subjects_from_db:
+                if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
+                    self.add_error('mpower_id', "mPower number already in use")
 
 
 def get_worker_from_args(kwargs):
@@ -83,6 +91,65 @@ def get_study_from_args(kwargs):
     return study
 
 
+def prepare_study_subject_fields(fields, study):
+    if study.columns.default_location:
+        fields['default_location'].required = True
+    else:
+        del fields['default_location']
+
+    if study.columns.type:
+        fields['type'].required = True
+    else:
+        del fields['type']
+
+    if not study.columns.nd_number:
+        del fields['nd_number']
+
+    if not study.columns.datetime_contact_reminder:
+        del fields['datetime_contact_reminder']
+
+    if not study.columns.postponed:
+        del fields['postponed']
+
+    if not study.columns.flying_team:
+        del fields['flying_team']
+
+    if not study.columns.mpower_id:
+        del fields['mpower_id']
+
+    if not study.columns.comments:
+        del fields['comments']
+
+    if not study.columns.referral:
+        del fields['referral']
+
+    if not study.columns.diagnosis:
+        del fields['diagnosis']
+
+    if not study.columns.year_of_diagnosis:
+        del fields['year_of_diagnosis']
+
+    if not study.columns.information_sent:
+        del fields['information_sent']
+
+    if not study.columns.pd_in_family:
+        del fields['pd_in_family']
+
+    if not study.columns.resigned and 'resigned' in fields:
+        del fields['resigned']
+
+    if not study.columns.resign_reason and 'resign_reason' in fields:
+        del fields['resign_reason']
+
+
+def validate_subject_screening_number(self, cleaned_data):
+    if self.study.columns.resign_reason:
+        subjects_from_db = StudySubject.objects.filter(screening_number=cleaned_data["screening_number"],
+                                                       study=self.study)
+        if len(subjects_from_db) > 0:
+            self.add_error('screening_number', "Screening number already in use")
+
+
 class StudySubjectAddForm(ModelForm):
     datetime_contact_reminder = forms.DateTimeField(label="Contact on",
                                                     widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
@@ -99,7 +166,7 @@ class StudySubjectAddForm(ModelForm):
         self.study = get_study_from_args(kwargs)
 
         super(ModelForm, self).__init__(*args, **kwargs)
-        self.fields['screening_number'].required = False
+        prepare_study_subject_fields(fields=self.fields, study=self.study)
 
     def save(self, commit=True):
         self.instance.study_id = self.study.id
@@ -116,12 +183,9 @@ class StudySubjectAddForm(ModelForm):
     def clean(self):
         cleaned_data = super(StudySubjectAddForm, self).clean()
         screening_number = self.build_screening_number(cleaned_data)
-        if screening_number is not None:
+        if screening_number is not None and self.study.columns.screening_number:
             cleaned_data['screening_number'] = screening_number
-            subjects_from_db = StudySubject.objects.filter(screening_number=screening_number)
-
-            if len(subjects_from_db) > 0:
-                self.add_error('screening_number', "Screening number already in use")
+        validate_subject_screening_number(self, cleaned_data)
         validate_subject_nd_number(self, cleaned_data)
         validate_subject_mpower_number(self, cleaned_data)
         return cleaned_data
@@ -178,6 +242,11 @@ class StudySubjectEditForm(ModelForm):
         instance = getattr(self, 'instance', None)
         if instance and instance.id:
             self.fields['screening_number'].widget.attrs['readonly'] = True
+        if instance and instance.study_id:
+            self.study = Study.objects.filter(id=instance.study_id)[0]
+        else:
+            self.study = Study(columns=StudyColumns())
+
         if was_resigned:
             self.fields['resigned'].disabled = True
 
diff --git a/smash/web/migrations/0073_auto_20171201_1034.py b/smash/web/migrations/0073_auto_20171201_1034.py
new file mode 100644
index 0000000000000000000000000000000000000000..d23196db8c602c9824645a587468ef700dc7587d
--- /dev/null
+++ b/smash/web/migrations/0073_auto_20171201_1034.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-01 10:34
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0072_auto_20171201_1013'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='studysubject',
+            name='default_location',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Location', verbose_name=b'Default appointment location'),
+        ),
+    ]
diff --git a/smash/web/migrations/0074_auto_20171201_1038.py b/smash/web/migrations/0074_auto_20171201_1038.py
new file mode 100644
index 0000000000000000000000000000000000000000..55297a5b043aec9a5285464223c44444586d3edc
--- /dev/null
+++ b/smash/web/migrations/0074_auto_20171201_1038.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-01 10:38
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0073_auto_20171201_1034'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='studysubject',
+            name='default_location',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Location', verbose_name=b'Default appointment location'),
+        ),
+    ]
diff --git a/smash/web/migrations/0075_auto_20171201_1252.py b/smash/web/migrations/0075_auto_20171201_1252.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d11beaa9167f3e0cd36d8688c1c2243e4a95d6c
--- /dev/null
+++ b/smash/web/migrations/0075_auto_20171201_1252.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-01 12:52
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0074_auto_20171201_1038'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='studysubject',
+            name='nd_number',
+            field=models.CharField(blank=True, max_length=25, verbose_name=b'ND number'),
+        ),
+        migrations.AlterField(
+            model_name='studysubject',
+            name='screening_number',
+            field=models.CharField(blank=True, max_length=50, null=True, verbose_name=b'Screening number'),
+        ),
+        migrations.AlterField(
+            model_name='studysubject',
+            name='type',
+            field=models.CharField(blank=True, choices=[(b'P', b'PATIENT'), (b'C', b'CONTROL')], max_length=1, null=True, verbose_name=b'Type'),
+        ),
+    ]
diff --git a/smash/web/models/study_subject.py b/smash/web/models/study_subject.py
index 29af95317831116ccb0bf01b162c31ad8d191db1..8bbeae76e223005167fc857d97465eff1c92af4f 100644
--- a/smash/web/models/study_subject.py
+++ b/smash/web/models/study_subject.py
@@ -50,28 +50,31 @@ class StudySubject(models.Model):
     )
     type = models.CharField(max_length=1,
                             choices=SUBJECT_TYPE_CHOICES.items(),
-                            verbose_name='Type'
+                            verbose_name='Type',
+                            null=True,
+                            blank=True
                             )
 
     default_location = models.ForeignKey(Location,
                                          verbose_name='Default appointment location',
+                                         null=True,
+                                         blank=True
                                          )
 
     flying_team = models.ForeignKey("web.FlyingTeam",
                                     verbose_name='Default flying team location (if applicable)',
-                                    null=True, blank=True
+                                    null=True,
+                                    blank=True
                                     )
 
     screening_number = models.CharField(max_length=50,
-                                        unique=True,
-                                        verbose_name='Screening number', blank=False, null=False
+                                        verbose_name='Screening number',
+                                        blank=True,
+                                        null=True
                                         )
     nd_number = models.CharField(max_length=25,
                                  blank=True,
                                  verbose_name='ND number',
-                                 validators=[
-                                     RegexValidator('^(ND[0-9]{4}|)$',
-                                                    message="ND number should look as follows: NDxxxx")]
                                  )
     mpower_id = models.CharField(max_length=20,
                                  blank=True,
diff --git a/smash/web/tests/forms/test_StudySubjectAddForm.py b/smash/web/tests/forms/test_StudySubjectAddForm.py
index 1a206bffd2f15ed731c8739850be714ad12e958f..6efd5c311d50663df0bd3374fdd484a6b4d1314f 100644
--- a/smash/web/tests/forms/test_StudySubjectAddForm.py
+++ b/smash/web/tests/forms/test_StudySubjectAddForm.py
@@ -3,7 +3,7 @@ import logging
 from web.forms import StudySubjectAddForm, get_new_screening_number
 from web.models.constants import SUBJECT_TYPE_CHOICES_CONTROL
 from web.tests import LoggedInWithWorkerTestCase
-from web.tests.functions import create_study_subject, create_subject, get_test_study
+from web.tests.functions import create_study_subject, create_subject, get_test_study, create_empty_study
 
 logger = logging.getLogger(__name__)
 
@@ -27,6 +27,11 @@ class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
         form.is_valid()
         self.assertTrue(form.is_valid())
 
+    def test_validation_for_study_without_columns(self):
+        form = StudySubjectAddForm(data=self.sample_data, user=self.user, study=create_empty_study())
+        form.is_valid()
+        self.assertTrue(form.is_valid())
+
     def test_invalid(self):
         form_data = self.sample_data
         form_data['screening_number'] = "123"
diff --git a/smash/web/tests/forms/test_StudySubjectEditForm.py b/smash/web/tests/forms/test_StudySubjectEditForm.py
index 5f838cff2724de1c31ae353a5e828d426d3bb002..57395339e3a78c6d21c48968fbd08cfc3b930e60 100644
--- a/smash/web/tests/forms/test_StudySubjectEditForm.py
+++ b/smash/web/tests/forms/test_StudySubjectEditForm.py
@@ -38,7 +38,7 @@ class StudySubjectEditFormTests(LoggedInWithWorkerTestCase):
         study_subject2.save()
 
         self.sample_data['nd_number'] = "ND0124"
-        edit_form = StudySubjectEditForm(self.sample_data)
+        edit_form = StudySubjectEditForm(self.sample_data, instance=self.study_subject)
 
         save_status = edit_form.is_valid()
         self.assertTrue("nd_number" in edit_form.errors)
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index 34401ae54e7827fd5cdef302e487ea9db8e07134..107bb0cb82d88b547e602297a5c2723764d89c93 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -28,6 +28,28 @@ def create_study(name="test"):
     return Study.objects.create(name=name, columns=study_columns)
 
 
+def create_empty_study(name="test"):
+    study_columns = StudyColumns.objects.create(
+        postponed=False,
+        datetime_contact_reminder=False,
+        type=False,
+        default_location=False,
+        flying_team=False,
+        screening_number=False,
+        nd_number=False,
+        mpower_id=False,
+        comments=False,
+        referral=False,
+        diagnosis=False,
+        year_of_diagnosis=False,
+        information_sent=False,
+        pd_in_family=False,
+        resigned=False,
+        resign_reason=False
+    )
+    return Study.objects.create(name=name, columns=study_columns)
+
+
 def get_test_location():
     locations = Location.objects.filter(name="test")
     if len(locations) > 0: