diff --git a/smash/smash/settings.py b/smash/smash/settings.py
index 76e4254370c88c384c06e885dc035e10126ab554..a327ecd64d4221f67bb45935c18143dd119c462f 100644
--- a/smash/smash/settings.py
+++ b/smash/smash/settings.py
@@ -20,8 +20,6 @@ PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
 
 DEBUG = True
 
-SHOW_VISITS_FROM_ZERO = True
-
 # Application definition
 
 INSTALLED_APPS = [
diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index f4f1a6e5f01f8ea5fbf2450be989cb641be5ebf6..74f7cd7670bbd612dd160e7a0f2998a88dd804e2 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -4,12 +4,13 @@ from django.db.models import Count, Case, When, Min, Max
 from django.db.models import Q
 from django.http import JsonResponse
 from django.urls import reverse
-from django.conf import settings
+from web.models import ConfigurationItem
+from distutils.util import strtobool
 
 from web.api_views.serialization_utils import bool_to_yes_no, flying_team_to_str, location_to_str, add_column, \
     serialize_date, serialize_datetime, get_filters_for_data_table_request, virus_test_to_str
 from web.models import StudySubject, Visit, Appointment, Subject, SubjectColumns, StudyColumns, Study, ContactAttempt
-from web.models.constants import SUBJECT_TYPE_CHOICES, GLOBAL_STUDY_ID
+from web.models.constants import SUBJECT_TYPE_CHOICES, GLOBAL_STUDY_ID, VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
 from web.models.study_subject_list import SUBJECT_LIST_GENERIC, SUBJECT_LIST_NO_VISIT, SUBJECT_LIST_REQUIRE_CONTACT, \
     StudySubjectList, SUBJECT_LIST_VOUCHER_EXPIRY
 from web.views import e500_error
@@ -79,7 +80,9 @@ def get_subject_columns(request, subject_list_type):
     add_column(result, "Excluded", "excluded", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Info sent", "information_sent", study_subject_columns, "yes_no_filter", study.columns)
 
-    if getattr(settings, "SHOW_VISITS_FROM_ZERO", False):
+    visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
+    #True values are y, yes, t, true, on and 1; false values are n, no, f, false, off and 0.
+    if strtobool(visit_from_zero):
         virus_visit_numbers = range(0, 5)
         visit_numbers = range(0, study.visits_to_show_in_subject_list + 0)
     else:
diff --git a/smash/web/api_views/visit.py b/smash/web/api_views/visit.py
index 596421c71842cd38ef67395c191a6e3be5291045..14c7021ffa5a1e07ab9aebad6d6dad88eebdb213 100644
--- a/smash/web/api_views/visit.py
+++ b/smash/web/api_views/visit.py
@@ -2,7 +2,8 @@ import logging
 
 from django.db.models import Q
 from django.http import JsonResponse
-from django.conf import settings
+from web.models import ConfigurationItem
+from distutils.util import strtobool
 
 from web.api_views.serialization_utils import bool_to_yes_no, flying_team_to_str, location_to_str, add_column, \
     serialize_date, get_filters_for_data_table_request
@@ -10,7 +11,7 @@ from web.models import AppointmentType, Appointment
 from web.models import SubjectColumns
 from web.templatetags.filters import display_visit_number
 from web.models import Visit, Study, VisitColumns, StudyVisitList, StudyColumns
-from web.models.constants import GLOBAL_STUDY_ID
+from web.models.constants import GLOBAL_STUDY_ID, VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
 from web.models.study_visit_list import VISIT_LIST_GENERIC, VISIT_LIST_EXCEEDED_TIME, VISIT_LIST_UNFINISHED, \
     VISIT_LIST_MISSING_APPOINTMENTS, VISIT_LIST_APPROACHING_WITHOUT_APPOINTMENTS, \
     VISIT_LIST_APPROACHING_FOR_MAIL_CONTACT
@@ -47,7 +48,9 @@ def get_visit_columns(request, visit_list_type):
     add_column(result, "Finished", "is_finished", visit_columns, "yes_no_filter")
     add_column(result, "Post mail sent", "post_mail_sent", visit_columns, "yes_no_filter")
     
-    if getattr(settings, "SHOW_VISITS_FROM_ZERO", False):
+    visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
+    #True values are y, yes, t, true, on and 1; false values are n, no, f, false, off and 0.
+    if strtobool(visit_from_zero):
         add_column(result, "Visit number", "display_visit_number", None, "from_zero_integer_filter")
     else:
         add_column(result, "Visit number", "visit_number", visit_columns, "integer_filter")
@@ -257,7 +260,9 @@ def serialize_visit(visit):
         "visible_appointment_types": appointment_types_to_str(appointment_types),
     }
 
-    if getattr(settings, "SHOW_VISITS_FROM_ZERO", False):
+    visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
+    #True values are y, yes, t, true, on and 1; false values are n, no, f, false, off and 0.
+    if strtobool(visit_from_zero):
         result["display_visit_number"] = display_visit_number(visit.visit_number)
 
     return result
diff --git a/smash/web/forms/study_subject_forms.py b/smash/web/forms/study_subject_forms.py
index d2d8bb507d1c1b0d91ab1ddb6a2af2565efea498..d051d12989cb3a5fb75e25c2c78fcdde264f554e 100644
--- a/smash/web/forms/study_subject_forms.py
+++ b/smash/web/forms/study_subject_forms.py
@@ -3,11 +3,12 @@ import re
 
 from django import forms
 from django.forms import ModelForm
-from django.conf import settings
+from web.models import ConfigurationItem
+from distutils.util import strtobool
 
 from web.forms.forms import DATETIMEPICKER_DATE_ATTRS, get_worker_from_args
 from web.models import StudySubject, Study, StudyColumns, VoucherType, Worker
-from web.models.constants import SCREENING_NUMBER_PREFIXES_FOR_TYPE
+from web.models.constants import SCREENING_NUMBER_PREFIXES_FOR_TYPE, VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
 from web.models.worker_study_role import WORKER_HEALTH_PARTNER
 from web.widgets.secure_file_widget import SecuredFileWidget
 
@@ -24,7 +25,9 @@ class StudySubjectForm(ModelForm):
         self.fields['health_partner'].queryset = Worker.get_workers_by_worker_type(
             WORKER_HEALTH_PARTNER)
         
-        if getattr(settings, "SHOW_VISITS_FROM_ZERO", False):
+        visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
+        #True values are y, yes, t, true, on and 1; false values are n, no, f, false, off and 0.
+        if strtobool(visit_from_zero):
             virus_visit_numbers = range(0, 5)
             for one_based_idx, virus_visit_number in enumerate(virus_visit_numbers, 1):
                 field = 'virus_test_{}'.format(one_based_idx)
diff --git a/smash/web/migrations/0166_auto_20200423_1457.py b/smash/web/migrations/0166_auto_20200423_1457.py
new file mode 100644
index 0000000000000000000000000000000000000000..093f4bb6dd5e998fa900385b6ddd749f6fea3936
--- /dev/null
+++ b/smash/web/migrations/0166_auto_20200423_1457.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2020-04-23 14:57
+from __future__ import unicode_literals
+
+from web.models.constants import VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
+from django.db import migrations
+
+
+def create_item(apps, type, value, name):
+    # We can't import the ConfigurationItem model directly as it may be a newer
+    # version than this migration expects. We use the historical version.
+    ConfigurationItem = apps.get_model("web", "ConfigurationItem")
+    item = ConfigurationItem.objects.create()
+    item.type = type
+    item.value = value
+    item.name = name
+    item.save()
+
+def configuration_items(apps, schema_editor):
+    create_item(apps, VISIT_SHOW_VISIT_NUMBER_FROM_ZERO, False,
+                "Should visit numbers be shown starting in 0")
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0165_configurationitem_email_virus'),
+    ]
+
+    operations = [
+        migrations.RunPython(configuration_items),
+    ]
\ No newline at end of file
diff --git a/smash/web/models/constants.py b/smash/web/models/constants.py
index 361c158e015311d495803b3073978541e978f0c6..51e7a70bcb8dc2f46892003cbe9fff9f67cba961 100644
--- a/smash/web/models/constants.py
+++ b/smash/web/models/constants.py
@@ -43,6 +43,8 @@ CONTACT_TYPES_CHOICES = (
     (CONTACT_TYPES_SMS, 'SMS'),
 )
 
+VISIT_SHOW_VISIT_NUMBER_FROM_ZERO = "VISIT_SHOW_VISIT_NUMBER_FROM_ZERO"
+
 CANCELLED_APPOINTMENT_COLOR_CONFIGURATION_TYPE = "CANCELLED_APPOINTMENT_COLOR"
 NO_SHOW_APPOINTMENT_COLOR_CONFIGURATION_TYPE = "NO_SHOW_APPOINTMENT_COLOR"
 
diff --git a/smash/web/templatetags/filters.py b/smash/web/templatetags/filters.py
index a6ba881218608a20fc19d5c4490a731ce6c128d5..218e34bc50f142b794a28ba7cf932b9de12c600a 100644
--- a/smash/web/templatetags/filters.py
+++ b/smash/web/templatetags/filters.py
@@ -1,9 +1,11 @@
 # See: http://stackoverflow.com/a/18962481
 from django import template
-from django.conf import settings
 from django.forms import CheckboxSelectMultiple, CheckboxInput
 from django.utils.safestring import mark_safe
 import datetime
+from web.models import ConfigurationItem
+from web.models.constants import VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
+from distutils.util import strtobool
 
 register = template.Library()
 
@@ -51,7 +53,9 @@ def timestamp(value):
 
 @register.filter(name='display_visit_number')
 def display_visit_number(visit_number):
-    if getattr(settings, "SHOW_VISITS_FROM_ZERO", False):
+    visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
+    #True values are y, yes, t, true, on and 1; false values are n, no, f, false, off and 0.
+    if strtobool(visit_from_zero):
         return (visit_number - 1)
     else:
         return visit_number
\ No newline at end of file