diff --git a/smash/web/api_views/appointment.py b/smash/web/api_views/appointment.py
index 92bfe8313235e19de33721e0d0e57d4c6a7f4979..45daed39fc115cfcec41ef904658132c65a3d776 100644
--- a/smash/web/api_views/appointment.py
+++ b/smash/web/api_views/appointment.py
@@ -187,7 +187,7 @@ def serialize_appointment(appointment: Appointment):
     nd_number = screening_number = phone_numbers = appointment_type_names = None
     status = appointment.status
     if appointment.visit is not None:
-        title = "Visit {}".format(display_visit_number(appointment.visit.visit_number))
+        title = f"Visit {display_visit_number(appointment.visit.visit_number)}"
         study_subject = appointment.visit.subject
         subject_string = study_subject.subject.last_name + " " + study_subject.subject.first_name
         first_name = study_subject.subject.first_name
diff --git a/smash/web/api_views/daily_planning.py b/smash/web/api_views/daily_planning.py
index 43d5ce071ae8ad9ff928bfd9931350c73700969f..5fd27ba65f73af52ef7af8c15e670b230a667764 100644
--- a/smash/web/api_views/daily_planning.py
+++ b/smash/web/api_views/daily_planning.py
@@ -15,32 +15,32 @@ from web.views.notifications import get_filter_locations
 logger = logging.getLogger(__name__)
 
 RANDOM_COLORS = [
-    '#%02X%02X%02X' % (8, 218, 217),
-    '#%02X%02X%02X' % (8, 8, 101),
-    '#%02X%02X%02X' % (8, 218, 3),
-    '#%02X%02X%02X' % (247, 137, 156),
-    '#%02X%02X%02X' % (183, 96, 2),
-    '#%02X%02X%02X' % (20, 106, 55),
-    '#%02X%02X%02X' % (8, 119, 217),
-    '#%02X%02X%02X' % (16, 76, 27),
-    '#%02X%02X%02X' % (85, 7, 162),
-    '#%02X%02X%02X' % (157, 7, 2),
-    '#%02X%02X%02X' % (49, 65, 68),
-    '#%02X%02X%02X' % (112, 124, 98),
-    '#%02X%02X%02X' % (8, 8, 215),
-    '#%02X%02X%02X' % (85, 7, 98),
-    '#%02X%02X%02X' % (16, 76, 100),
-    '#%02X%02X%02X' % (85, 7, 50),
-    '#%02X%02X%02X' % (183, 5, 2),
-    '#%02X%02X%02X' % (183, 156, 2),
-    '#%02X%02X%02X' % (112, 82, 38),
+    f'#{8:02X}{218:02X}{217:02X}',
+    f'#{8:02X}{8:02X}{101:02X}',
+    f'#{8:02X}{218:02X}{3:02X}',
+    f'#{247:02X}{137:02X}{156:02X}',
+    f'#{183:02X}{96:02X}{2:02X}',
+    f'#{20:02X}{106:02X}{55:02X}',
+    f'#{8:02X}{119:02X}{217:02X}',
+    f'#{16:02X}{76:02X}{27:02X}',
+    f'#{85:02X}{7:02X}{162:02X}',
+    f'#{157:02X}{7:02X}{2:02X}',
+    f'#{49:02X}{65:02X}{68:02X}',
+    f'#{112:02X}{124:02X}{98:02X}',
+    f'#{8:02X}{8:02X}{215:02X}',
+    f'#{85:02X}{7:02X}{98:02X}',
+    f'#{16:02X}{76:02X}{100:02X}',
+    f'#{85:02X}{7:02X}{50:02X}',
+    f'#{183:02X}{5:02X}{2:02X}',
+    f'#{183:02X}{156:02X}{2:02X}',
+    f'#{112:02X}{82:02X}{38:02X}',
 ]
 
 
 def build_duration(duration):
     number_of_hours = duration // 60
     minutes = duration - number_of_hours * 60
-    return "{0:02d}:{1:02d}".format(number_of_hours, minutes)
+    return f"{number_of_hours:02d}:{minutes:02d}"
 
 
 def get_holidays(worker, date):
@@ -254,7 +254,7 @@ def get_generic_appointment_events(request: HttpRequest, date: str, include_all:
             'short_title': appointment.title(),
             'status': appointment.status,
             'duration': build_duration(appointment.length),
-            'id': 'app-{}'.format(appointment.id),
+            'id': f'app-{appointment.id}',
             'appointment_id': appointment.id,
             'link_when': link_when,
             'link_who': appointment.worker_assigned_id,
@@ -330,7 +330,7 @@ def events(request: HttpRequest, date: str, include_all=False):
                 'short_title': link.appointment_type.code,
                 'duration': build_duration(link.appointment_type.default_duration),
                 'subject': str(appointment_subject),
-                'id': '{}-{}'.format(i, j),
+                'id': f'{i}-{j}',
                 'link_id': link.id,
                 'link_when': link_when,
                 'link_who': link.worker_id,
diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index 5c65679865d7243ed197b0ea3c7fc78bb96d704f..27cfcaa71affbae2c5978b95abfc811cc11e7240 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -157,8 +157,8 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
     add_column(result, "Edit", "edit", study_subject_list, None, sortable=False)
 
     for one_based_idx, visit_number in enumerate(visit_numbers, 1):
-        visit_key = "visit_{}".format(one_based_idx)  # always starts in 1
-        add_column(result, "Visit {}".format(visit_number), visit_key, None,
+        visit_key = f"visit_{one_based_idx}"  # always starts in 1
+        add_column(result, f"Visit {visit_number}", visit_key, None,
                    "visit_filter", visible_param=study_subject_list.visits)
 
     return JsonResponse({"columns": result})
@@ -531,7 +531,7 @@ def serialize_subject(study_subject: StudySubject):
         else:
             status = "UPCOMING"
 
-        appointment_types = ['{} ({})'.format(at.code, at.description) for at in visit.appointment_types.all()]
+        appointment_types = [f'{at.code} ({at.description})' for at in visit.appointment_types.all()]
         if len(appointment_types) == 0:
             appointment_types = ['No appointment types set.']
 
diff --git a/smash/web/api_views/worker.py b/smash/web/api_views/worker.py
index 1945d1dd717f9b8e5eb655b6af7c7419847824ce..1c0fa279aef7a20cbfc7b5afb6a144f4950a990f 100644
--- a/smash/web/api_views/worker.py
+++ b/smash/web/api_views/worker.py
@@ -50,7 +50,7 @@ def workers_for_daily_planning(request):
             'id': worker.id,
             'flags': [language.image.url for language in worker.languages.all() if language.image],
             'availability': worker.availability_percentage(start_date=start_date),
-            'title': "{} ({})".format(str(worker), role[:1].upper()),
+            'title': f"{str(worker)} ({role[:1].upper()})",
             'role': role
         }
         workers_list_for_json.append(worker_dict_for_json)
diff --git a/smash/web/debug_utils.py b/smash/web/debug_utils.py
index ac29092477242841e027855d1f973496fbf478f6..c2f98d5db2890c870c1bfc3b72a9c1e981fdef63 100644
--- a/smash/web/debug_utils.py
+++ b/smash/web/debug_utils.py
@@ -15,7 +15,7 @@ def timeit(method):
             name = kw.get('log_name', method.__name__.upper())
             kw['log_time'][name] = int((end_time - start_time) * 1000)
         else:
-            print('%r  %2.2f ms' % (method.__name__, (end_time - start_time) * 1000))
+            print(f'{method.__name__!r}  {(end_time - start_time) * 1000:2.2f} ms')
         return result
 
     return timed
diff --git a/smash/web/forms/appointment_form.py b/smash/web/forms/appointment_form.py
index 1bdffc8fefdfbcfcdd543532f584962d977ec372..09b8a9c6ba053b96c5faa3e758f3160e030a8f3c 100644
--- a/smash/web/forms/appointment_form.py
+++ b/smash/web/forms/appointment_form.py
@@ -64,7 +64,7 @@ class AppointmentForm(ModelForm):
                     old_human_values = ''
                     previous_value = ''
                 # description
-                description = '{} changed from "{}" to "{}"'.format(field, old_human_values, new_human_values)
+                description = f'{field} changed from "{old_human_values}" to "{new_human_values}"'
             else:
                 if self.instance.id:  # update instance
                     previous_value = getattr(self.instance, field)
@@ -72,7 +72,7 @@ class AppointmentForm(ModelForm):
                     previous_value = ''
                 if isinstance(new_value, QuerySet):
                     new_value = ','.join([str(element.id) for element in new_value])  # overwrite variable
-                description = '{} changed from "{}" to "{}"'.format(field, previous_value, new_value)
+                description = f'{field} changed from "{previous_value}" to "{new_value}"'
 
             p = Provenance(modified_table=Appointment._meta.db_table,
                            modified_table_id=self.instance.id,
diff --git a/smash/web/forms/study_subject_forms.py b/smash/web/forms/study_subject_forms.py
index 0ee05ec24b101367d40179dcddb5d9bd3caaf1e6..8027773ccae4d4f4e4e3aa427b1ca2c3bb8ca9ea 100644
--- a/smash/web/forms/study_subject_forms.py
+++ b/smash/web/forms/study_subject_forms.py
@@ -76,10 +76,10 @@ def create_field_for_custom_study_subject_field(study_subject_field: CustomStudy
                 url = ''
 
                 def __str__(self):
-                    return "%s" % self.url
+                    return f"{self.url}"
 
                 def __unicode__(self):
-                    return "%s" % self.url
+                    return f"{self.url}"
 
             initial = CustomFileField()
             initial.url = val
diff --git a/smash/web/importer/etl_common.py b/smash/web/importer/etl_common.py
index a5b204d8d3ac194148862e8ef5c0b64bcb5cbe38..dc3ba581ad46ba3633222abcee36373ddcaeab3d 100644
--- a/smash/web/importer/etl_common.py
+++ b/smash/web/importer/etl_common.py
@@ -54,7 +54,7 @@ class EtlCommon:
 
     def create_provenance(self, field_name: str, new_value: object, object_to_change: models.Model,
                           object_type: Type[models.Model], old_value: object) -> Provenance:
-        description = '{} changed from "{}" to "{}"'.format(field_name, old_value, new_value)
+        description = f'{field_name} changed from "{old_value}" to "{new_value}"'
         p = Provenance(modified_table=object_type._meta.db_table,
                        modified_table_id=object_to_change.id,
                        modification_author=self.etl_data.import_worker,
diff --git a/smash/web/importer/importer_cron_job.py b/smash/web/importer/importer_cron_job.py
index 3947d03a34ad35ce1413ce3584f4f6b0ec461a34..195152ba8b14fbf8383bebfc69baedba0cb436df 100644
--- a/smash/web/importer/importer_cron_job.py
+++ b/smash/web/importer/importer_cron_job.py
@@ -58,8 +58,7 @@ class SubjectImporterCronJob(CronJobBase):
                 importer.execute()
                 email_body = importer.get_summary()
                 EmailSender.send_email(email_title,
-                                       "<h3>Data was successfully imported from file: {}</h3>{}".format(filename,
-                                                                                                        email_body),
+                                       f"<h3>Data was successfully imported from file: {filename}</h3>{email_body}",
                                        email_recipients)
                 backup_file(filename)
                 return "import is successful"
@@ -67,10 +66,10 @@ class SubjectImporterCronJob(CronJobBase):
             except BaseException:
                 tb = traceback.format_exc()
                 EmailSender.send_email(email_title,
-                                       "<h3><font color='red'>There was a problem with importing data from file: "
-                                       "{}</font></h3><pre>{}</pre>".format(filename, tb),
+                                       f"<h3><font color='red'>There was a problem with importing data from file: "
+                                       "{filename}</font></h3><pre>{tb}</pre>",
                                        email_recipients)
-                logger.exception('There was a problem with importing data from file: %s', filename)
+                logger.exception(f'There was a problem with importing data from file: {filename}')
                 return "import crashed"
 
 
@@ -113,8 +112,7 @@ class VisitImporterCronJob(CronJobBase):
                 importer.load_data()
                 email_body = importer.get_summary()
                 EmailSender.send_email(email_title,
-                                       "<h3>Data was successfully imported from file: {}</h3>{}".format(filename,
-                                                                                                        email_body),
+                                       f"<h3>Data was successfully imported from file: {filename}</h3>{email_body}",
                                        email_recipients)
                 backup_file(filename)
                 return "import is successful"
@@ -123,9 +121,9 @@ class VisitImporterCronJob(CronJobBase):
                 tb = traceback.format_exc()
                 EmailSender.send_email(email_title,
                                        "<h3><font color='red'>There was a problem with importing data from file: "
-                                       "{}</font></h3><pre>{}</pre>".format(filename, tb),
+                                       f"{filename}</font></h3><pre>{tb}</pre>",
                                        email_recipients)
-                logger.exception("There was a problem with importing data from file: %s", filename)
+                logger.exception(f"There was a problem with importing data from file: {filename}")
                 return "import crashed"
 
 
diff --git a/smash/web/management/commands/holidays.py b/smash/web/management/commands/holidays.py
index 3f6a9c6fc68bc6cca9f0f76a2b41a1af6457cdfa..8804121a0d32d5c66889642e7459a5ad31983a72 100644
--- a/smash/web/management/commands/holidays.py
+++ b/smash/web/management/commands/holidays.py
@@ -22,7 +22,7 @@ class Command(BaseCommand):
     def handle(self, *args, **options):
         for location in Location.objects.exclude(name="Flying Team").all():
             for year in options['year']:
-                self.stdout.write("importing holidays for year {} and location {}".format(year, location))
+                self.stdout.write(f"importing holidays for year {year} and location {location}")
                 # new years day
                 self.create_holiday(year, 1, 1, "New Years Day", location)
                 # easter monday
@@ -53,7 +53,7 @@ class Command(BaseCommand):
                                            location=location, comment=comment).count()
         if count != 0:
             self.stdout.write(
-                'an holiday with the same description already exists for the same day: {}'.format(comment))
+                f'an holiday with the same description already exists for the same day: {comment}')
             return
         holiday = Appointment()
         holiday.datetime_when = datetime.datetime(year=year, month=month, day=day, hour=9)
diff --git a/smash/web/migrations/0001_initial.py b/smash/web/migrations/0001_initial.py
index 7d3f9800878b0d32e9b1a011bd12d7e3a57bd432..36267b3798672f7d38b5f5e4d6fe2d0235e99ede 100644
--- a/smash/web/migrations/0001_initial.py
+++ b/smash/web/migrations/0001_initial.py
@@ -8,7 +8,6 @@ import django.db.models.deletion
 
 
 class Migration(migrations.Migration):
-
     initial = True
 
     dependencies = [
diff --git a/smash/web/models/availability.py b/smash/web/models/availability.py
index 2513da6899476b3e08bb413db27dc29960cf5496..7a43b308acd8f44b14cadceb72da548329c9899d 100644
--- a/smash/web/models/availability.py
+++ b/smash/web/models/availability.py
@@ -25,7 +25,7 @@ class Availability(models.Model):
 
     def __str__(self):
         day_of_week = self.get_day_of_week_as_string()
-        return "%s %s %s" % (day_of_week, self.person.last_name, self.person.first_name)
+        return f"{day_of_week} {self.person.last_name} {self.person.first_name}"
 
     def get_day_of_week_as_string(self):
         day_of_week = "N/A"
diff --git a/smash/web/models/configuration_item.py b/smash/web/models/configuration_item.py
index b050a5ef0aeb834acf340f0e9808fba96fa0e9db..23a15f40a0db5c224757d4988d2f7c34c04409f6 100644
--- a/smash/web/models/configuration_item.py
+++ b/smash/web/models/configuration_item.py
@@ -44,7 +44,7 @@ class ConfigurationItem(models.Model):
                                   )
 
     def __str__(self):
-        return "%s %s" % (self.name, self.value)
+        return f"{self.name} {self.value}"
 
     @staticmethod
     def is_valid(item: 'ConfigurationItem') -> bool:
@@ -67,7 +67,7 @@ class ConfigurationItem(models.Model):
         if item.type == KIT_RECIPIENT_EMAIL_CONFIGURATION_TYPE:
             for email in item.value.split(";"):
                 if email != '' and not is_valid_email(email):
-                    return "Email {} address is invalid".format(email)
+                    return f"Email {email} address is invalid"
 
         if item.type == DEFAULT_FROM_EMAIL:
             if not is_valid_email(item.value):
diff --git a/smash/web/models/contact_attempt.py b/smash/web/models/contact_attempt.py
index ffadd6c779182f633c87cc043c6b1953ceb1e8d9..8eef7306cb902499af23fde26fc56f18568bd525 100644
--- a/smash/web/models/contact_attempt.py
+++ b/smash/web/models/contact_attempt.py
@@ -22,4 +22,4 @@ class ContactAttempt(models.Model):
     comment = models.TextField(max_length=1024, null=True, blank=True)
 
     def __str__(self):
-        return "%s %s" % (self.subject, self.worker)
+        return f"{self.subject} {self.worker}"
diff --git a/smash/web/models/flying_team.py b/smash/web/models/flying_team.py
index 73ed2b4c3278324115c327a23addc92435936303..6ed1133e32a81158ec4031b977f33fcca6f13ff0 100644
--- a/smash/web/models/flying_team.py
+++ b/smash/web/models/flying_team.py
@@ -9,4 +9,4 @@ class FlyingTeam(models.Model):
     place = models.CharField(max_length=255, verbose_name='Place')
 
     def __str__(self):
-        return "%s" % self.place
+        return f"{self.place}"
diff --git a/smash/web/models/holiday.py b/smash/web/models/holiday.py
index f47b696233d3edf97a0fac0cf794fa17358aa2a9..1c56e39361b965f0a3f0b58f21aa37cedff509bd 100644
--- a/smash/web/models/holiday.py
+++ b/smash/web/models/holiday.py
@@ -29,4 +29,4 @@ class Holiday(models.Model):
                             help_text='Defines the kind of availability. Either Holiday or Extra Availability.')
 
     def __str__(self):
-        return "%s %s" % (self.person.first_name, self.person.last_name)
+        return f"{self.person.first_name} {self.person.last_name}"
diff --git a/smash/web/models/language.py b/smash/web/models/language.py
index 7b8c1b20820b0ecda13888f344ad9c0f73a63555..55eeada975b4d66761d396984b0c7fc81ada89cc 100644
--- a/smash/web/models/language.py
+++ b/smash/web/models/language.py
@@ -40,7 +40,7 @@ class Language(models.Model):
 
     def image_img(self):
         if self.image:
-            return '<img class="flag-icon" src="%s" />' % self.image.url
+            return f'<img class="flag-icon" src="{self.image.url}" />'
         else:
             return 'No image'
 
diff --git a/smash/web/models/location.py b/smash/web/models/location.py
index e817d3797d3d9ed307ffb2b6bd8d599c4d8d0efd..ff3409199ade5c17dc6db4d11f0429d7d200d1bf 100644
--- a/smash/web/models/location.py
+++ b/smash/web/models/location.py
@@ -20,4 +20,4 @@ class Location(models.Model):
                                   )
 
     def __str__(self):
-        return "%s" % self.name
+        return f"{self.name}"
diff --git a/smash/web/models/mail_template.py b/smash/web/models/mail_template.py
index a0309f346b4635b2c37fa22bd38b3701150ea0f3..decb5b1cd7e0f88d8608175b618c688a1d39a861 100644
--- a/smash/web/models/mail_template.py
+++ b/smash/web/models/mail_template.py
@@ -334,8 +334,7 @@ class MailTemplate(models.Model):
                 voucher_type += ' (' + voucher.activity_type + ")"
             return {
                 "##C_NUMBER##": voucher.number,
-                "##C_PATIENT_NAME##": '{} {}'.format(voucher.study_subject.subject.first_name,
-                                                     voucher.study_subject.subject.last_name),
+                "##C_PATIENT_NAME##": f'{voucher.study_subject.subject.first_name} {voucher.study_subject.subject.last_name}',
                 "##C_VOUCHER_TYPE##": voucher_type,
                 "##C_ISSUE_DATE_SHORT##": voucher.issue_date.strftime(DATE_FORMAT_SHORT),
                 "##C_EXPIRY_START_SHORT##": voucher.expiry_date.strftime(DATE_FORMAT_SHORT),
diff --git a/smash/web/models/room.py b/smash/web/models/room.py
index 906ed46a2f8feea3d8db2ff2db7a906fbfd07eb9..d187a253b71476edca17135812e090c8da5d5a2c 100644
--- a/smash/web/models/room.py
+++ b/smash/web/models/room.py
@@ -31,4 +31,4 @@ class Room(models.Model):
                                   )
 
     def __str__(self):
-        return "%d %s %s" % (self.room_number, self.address, self.city)
+        return f"{self.room_number} {self.address} {self.city}"
diff --git a/smash/web/models/study.py b/smash/web/models/study.py
index e7e774290fd1769bc303d4d13435eb9b679f3cc7..14eb77e6a086ae9d800063eaddca1cc7ce4cbdff 100644
--- a/smash/web/models/study.py
+++ b/smash/web/models/study.py
@@ -89,7 +89,7 @@ class Study(models.Model):
         return regex.match(nd_number) is not None
 
     def __str__(self):
-        return "%s" % self.name
+        return f"{self.name}"
 
     @property
     def has_vouchers(self):
diff --git a/smash/web/models/study_subject.py b/smash/web/models/study_subject.py
index 4f95e0eb00a406adde17df5bc5e43d2f157008c3..52a5b90c81fa6759c3f6ac667657d3df69ac2eab 100644
--- a/smash/web/models/study_subject.py
+++ b/smash/web/models/study_subject.py
@@ -257,7 +257,7 @@ class StudySubject(models.Model):
                                                        study_subject_field=custom_study_subject_field))
 
     def __str__(self):
-        return "%s %s" % (self.subject.first_name, self.subject.last_name)
+        return f"{self.subject.first_name} {self.subject.last_name}"
 
     def get_custom_data_value(self, custom_field: CustomStudySubjectField) -> Optional[CustomStudySubjectValue]:
         for value in self.custom_data_values:
diff --git a/smash/web/models/subject.py b/smash/web/models/subject.py
index 4d863e3dc239abea0272a1276841312271b5c54d..c704304db4cc058faa5fcc33e9063c01e4968ebd 100644
--- a/smash/web/models/subject.py
+++ b/smash/web/models/subject.py
@@ -128,7 +128,7 @@ class Subject(models.Model):
     )
 
     def pretty_address(self):
-        return '{} ({}), {}. {}'.format(self.address, self.postal_code, self.city, self.country)
+        return f'{self.address} ({self.postal_code}), {self.city}. {self.country}'
 
     def mark_as_dead(self):
         self.dead = True
@@ -149,7 +149,7 @@ class Subject(models.Model):
             appointment.save()
 
     def __str__(self):
-        return "%s %s" % (self.first_name, self.last_name)
+        return f"{self.first_name} {self.last_name}"
 
 
 # SIGNALS
@@ -159,7 +159,7 @@ def set_as_deceased(sender, instance, **kwargs):  # pylint: disable=unused-argum
         p = Provenance(modified_table=Subject._meta.db_table,
                        modified_table_id=instance.id, modification_author=None,
                        previous_value=instance.dead, new_value=True,
-                       modification_description='Subject "{}" marked as dead'.format(instance),
+                       modification_description=f'Subject "{instance}" marked as dead',
                        modified_field='dead',
                        )
         instance.mark_as_dead()
diff --git a/smash/web/models/subject_type.py b/smash/web/models/subject_type.py
index 37a422d23e14b91af37cbed3c9009547d8edd0e4..bbd04952cd4de53017f7e7a03adb13d43440cd06 100644
--- a/smash/web/models/subject_type.py
+++ b/smash/web/models/subject_type.py
@@ -49,4 +49,4 @@ class SubjectType(models.Model):
     )
 
     def __str__(self):
-        return "%s" % self.name
+        return f"{self.name}"
diff --git a/smash/web/models/voucher.py b/smash/web/models/voucher.py
index 20d51ae0f610474d14f34c709f7c95ab575f0d8d..b3724421e5076433dd0a90c10019f26a9b6c05d1 100644
--- a/smash/web/models/voucher.py
+++ b/smash/web/models/voucher.py
@@ -71,4 +71,4 @@ class Voucher(models.Model):
     )
 
     def __str__(self):
-        return "%s - %s %s" % (self.number, self.study_subject.subject.first_name, self.study_subject.subject.last_name)
+        return f"{self.number} - {self.study_subject.subject.first_name} {self.study_subject.subject.last_name}"
diff --git a/smash/web/models/voucher_type.py b/smash/web/models/voucher_type.py
index 64b51d0cca3b0de159e0f457f1b464128bd2b7ab..78663ebfe9232923808d3e9e097478b64cd6ee95 100644
--- a/smash/web/models/voucher_type.py
+++ b/smash/web/models/voucher_type.py
@@ -19,4 +19,4 @@ class VoucherType(models.Model):
     )
 
     def __str__(self):
-        return "%s (%s)" % (self.code, self.description)
+        return f"{self.code} ({self.description})"
diff --git a/smash/web/models/worker.py b/smash/web/models/worker.py
index f54b8c280acb5764795e173ad3cc2d9568544fc1..6f8e7fc13c9aea7a610a52032cfab6eac6059cb0 100644
--- a/smash/web/models/worker.py
+++ b/smash/web/models/worker.py
@@ -44,7 +44,7 @@ def role_choices_by_worker_type(worker_type):
     elif worker_type == WORKER_VOUCHER_PARTNER:
         return VOUCHER_PARTNER_ROLE_CHOICES
     else:
-        raise TypeError("{} Unknown worker type".format(worker_type))
+        raise TypeError(f"{worker_type} Unknown worker type")
 
 
 def worker_type_by_worker(worker):
@@ -229,7 +229,7 @@ class Worker(models.Model):
             start_date = start_date.replace(hour=0, minute=0, second=0)
             end_date = start_date + datetime.timedelta(days=1)
 
-        office_availability = OfficeAvailability('{} {}'.format(self.first_name, self.last_name), start=start_date,
+        office_availability = OfficeAvailability(f'{self.first_name} {self.last_name}', start=start_date,
                                                  end=end_date)
 
         # Subject Appointments
@@ -329,11 +329,11 @@ class Worker(models.Model):
     def __str__(self):
         if self.name != '':
             if self.first_name == '':
-                return "%s (%s, %s)" % (self.name, self.address, self.city)
+                return f"{self.name} ({self.address}, {self.city})"
             else:
-                return "%s %s %s" % (self.name, self.first_name, self.last_name)
+                return f"{self.name} {self.first_name} {self.last_name}"
         else:
-            return "%s %s" % (self.first_name, self.last_name)
+            return f"{self.first_name} {self.last_name}"
 
     def initials(self):
         result = ""
diff --git a/smash/web/nexmo_gateway.py b/smash/web/nexmo_gateway.py
index 70a116f4a39d88fd2cfaf958fa0a44ac99296486..682d795dca327d4cb1ca3c7ef9752ae2152f1b01 100644
--- a/smash/web/nexmo_gateway.py
+++ b/smash/web/nexmo_gateway.py
@@ -36,7 +36,7 @@ class Nexmo:
             self.default_from = "SMASCH"
 
     def send_sms(self, device, token):
-        body = 'Your authentication token is %s' % token
+        body = f'Your authentication token is {token}'
         phone_number = device.number.as_e164
         logger.info("Sending authentication token to %s", phone_number)
         self.client.send_message({'to': phone_number, 'from': self.default_from, 'text': body})
diff --git a/smash/web/officeAvailability.py b/smash/web/officeAvailability.py
index d9f26ad2781dcf25822605d2e95e9b3324804323..9b6c84dbfcb41f77c2098c5c1a72a5f05a70b2c3 100644
--- a/smash/web/officeAvailability.py
+++ b/smash/web/officeAvailability.py
@@ -246,12 +246,12 @@ class OfficeAvailability:
             n_ticks = int(minutes / 60)
             if n_ticks == 0:
                 n_ticks = 1
-            xticks = self.availability.asfreq('{}T'.format(n_ticks)).index
+            xticks = self.availability.asfreq(f'{n_ticks}T').index
         else:
-            xticks = self.availability.asfreq('{}H'.format(n_ticks)).index
+            xticks = self.availability.asfreq(f'{n_ticks}H').index
 
-        title = 'Availability for {} from {} to {}'.format(self.name, self.start.strftime('%Y/%m/%d %H:%M'),
-                                                           self.end.strftime('%Y/%m/%d %H:%M'))
+        title = f'Availability for {self.name} from {self.start.strftime("%Y/%m/%d %H:%M")}'\
+                 ' to {self.end.strftime("%Y/%m/%d %H:%M")}'
 
         axes = self.availability.plot(figsize=(16, 8), grid=True,
                                       title=title, legend=True, label='Availability', color='#00af52',
@@ -268,4 +268,4 @@ class OfficeAvailability:
 
         fig.tight_layout()
         fig.savefig(
-            '{}_{}_{}.pdf'.format(self.name, self.start.strftime('%Y%m%d%H%M'), self.end.strftime('%Y%m%d%H%M')))
+            f"{self.name}_{self.start.strftime('%Y%m%d%H%M')}_{self.end.strftime('%Y%m%d%H%M')}.pdf")
diff --git a/smash/web/redcap_connector.py b/smash/web/redcap_connector.py
index 2ecfb5a288d0038014b123185b3c7f458619037a..77550c1fc9fbf3dc5cb1d6daeec1e992263b441c 100644
--- a/smash/web/redcap_connector.py
+++ b/smash/web/redcap_connector.py
@@ -246,10 +246,8 @@ class RedcapConnector:
                         for smasch_appointment in smasch_appointments:
                             smasch_appointment.mark_as_finished()
                             if not smasch_appointment.visit.is_finished:
-                                description = '{} changed from "{}" to "{}"'.format(
-                                    'is_finished',
-                                    smasch_appointment.visit.is_finished,
-                                    True)
+                                description = f'is_finished changed from "{smasch_appointment.visit.is_finished}"'\
+                                     ' to "{True}"'
                                 p = Provenance(modified_table=Visit._meta.db_table,
                                                modified_table_id=smasch_appointment.visit.id,
                                                modification_author=self.importer_user,
@@ -270,11 +268,11 @@ class RedcapConnector:
             changes = []
             for i in range(1, 6):
                 if visit.visit_number == i:
-                    result_label = "Virus {} RT-PCR".format(i - 1)
-                    updated_label = "Visit {} RT-PCR update date".format(i - 1)
-                    collect_label = "Visit {} RT-PCR collection date".format(i - 1)
-                    iga_label = "Visit {} IgA Status".format(i - 1)
-                    igg_label = "Visit {} IgG Status".format(i - 1)
+                    result_label = f"Virus {i - 1} RT-PCR"
+                    updated_label = f"Visit {i - 1} RT-PCR update date"
+                    collect_label = f"Visit {i - 1} RT-PCR collection date"
+                    iga_label = f"Visit {i - 1} IgA Status"
+                    igg_label = f"Visit {i - 1} IgG Status"
                     if subject.get_custom_field_value(result_label) != visit.virus:
                         changes.extend([(result_label, visit.virus),
                                         (updated_label, datetime.datetime.now().strftime("%Y-%m-%d"))])
@@ -290,7 +288,7 @@ class RedcapConnector:
             if len(changes) > 0:
                 for field, new_value in changes:
                     old_value = subject.get_custom_field_value(field)
-                    description = '{} changed from "{}" to "{}"'.format(field, old_value, new_value)
+                    description = f'{field} changed from "{old_value}" to "{new_value}"'
                     p = Provenance(modified_table=StudySubject._meta.db_table,
                                    modified_table_id=subject.id,
                                    modification_author=self.importer_user,
diff --git a/smash/web/statistics.py b/smash/web/statistics.py
index fe921afa2be5a1e256aab5d727c17f412d6eb8cd..75991b35fca4b40715fd8fd4e8f3119bc63151af 100644
--- a/smash/web/statistics.py
+++ b/smash/web/statistics.py
@@ -155,7 +155,7 @@ class StatisticsManager:
             query = QUERY_APPOINTMENTS
             subject_type_clause = ""
             if subject_type is not None:
-                subject_type_clause = " AND web_studysubject.type_id = '{}'".format(subject_type.id)
+                subject_type_clause = f" AND web_studysubject.type_id = '{subject_type.id}'"
             query = query.format(subject_type_clause)
             with connection.cursor() as cursor:
                 cursor.execute(query, [visit, month, year])
@@ -178,7 +178,7 @@ class StatisticsManager:
     def _get_count_from_filters_or_sql(model, filters, query, visit, month, year, subject_type: SubjectType):
         if visit:
             if subject_type is not None:
-                query += " AND web_studysubject.type_id = '{}'".format(subject_type.id)
+                query += f" AND web_studysubject.type_id = '{subject_type.id}'"
             with connection.cursor() as cursor:
                 cursor.execute(
                     query,
diff --git a/smash/web/templatetags/filters.py b/smash/web/templatetags/filters.py
index bdf70fbd093eaad63a4c50d0d8761df74a4df9f8..718e488e540118317a47af12f9178c39692ad695 100644
--- a/smash/web/templatetags/filters.py
+++ b/smash/web/templatetags/filters.py
@@ -25,8 +25,8 @@ def add_class(value, arg):
     # Filter out zero-length class names ('')
     css_classes = [x for x in css_classes if len(x) > 0]
     # Convert list to string
-    css_classes = reduce(lambda a, x: "%s %s" % (a, x), css_classes, "")
-    css_classes = '%s %s' % (css_classes, arg)
+    css_classes = reduce(lambda a, x: f"{a} {x}", css_classes, "")
+    css_classes = f'{css_classes} {arg}'
     # Return the widget with freshly crafted classes
     return value.as_widget(attrs={'class': css_classes})
 
@@ -46,7 +46,7 @@ def is_checkbox(value):
 def render_appointments(statistics, appointment_type):
     html = ""
     for status_count in statistics.get(appointment_type, []):
-        html += '<td>{}</td>'.format(status_count)
+        html += f'<td>{status_count}</td>'
     return mark_safe(html)
 
 
diff --git a/smash/web/tests/forms/test_AppointmentEditForm.py b/smash/web/tests/forms/test_AppointmentEditForm.py
index dbf300b604ea69f079f421eeed762b9679bedd57..1a54a14a08c3e53b1acf16775ee9e7eddbf1754f 100644
--- a/smash/web/tests/forms/test_AppointmentEditForm.py
+++ b/smash/web/tests/forms/test_AppointmentEditForm.py
@@ -68,7 +68,7 @@ class AppointmentEditFormTests(TestCase):
         # check that the appointment links have been deleted and recreated
         links_count = AppointmentTypeLink.objects.filter(appointment=self.appointment).count()
         self.assertEqual(1, links_count,
-                         "only one appointment link should exist, {} found".format(links_count))
+                         f"only one appointment link should exist, {links_count} found")
         new_link = AppointmentTypeLink.objects.filter(appointment=self.appointment).first()
         self.assertNotEqual(link, new_link)
         self.assertIsNone(new_link.worker)
@@ -93,7 +93,7 @@ class AppointmentEditFormTests(TestCase):
         # check that the appointment links have been kept
         links_count = AppointmentTypeLink.objects.filter(appointment=self.appointment).count()
         self.assertEqual(1, links_count,
-                         "only one appointment link should exist, {} found".format(links_count))
+                         f"only one appointment link should exist, {links_count} found")
         new_link = AppointmentTypeLink.objects.filter(appointment=self.appointment).first()
         self.assertEqual(link.id, new_link.id)
         self.assertEqual(self.worker, new_link.worker)
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index 5e22975ed1c393fe96d0766630073720f2ca8bff..51d91ea3e089bcc4d87e9c376fc83cef3ab18d39 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -223,7 +223,7 @@ def create_study_subject_with_multiple_screening_numbers(subject_id=1, subject=N
         subject = create_subject()
 
     if screening_number is None:
-        screening_number = 'E-00{first_id}; L-00{second_id}'.format(first_id=subject_id, second_id=subject_id)
+        screening_number = f'E-00{subject_id}; L-00{subject_id}'
     return StudySubject.objects.create(
         default_location=get_test_location(),
         type=get_control_subject_type(),
@@ -433,7 +433,7 @@ def datetimeify_date(date: Union[datetime.date, str, bytes]) -> datetime.datetim
 
     actual_type = str(type(date))
     raise TypeError(
-        "Date should be either a subclass of 'datetime.date', string or bytes! But is: {} instead".format(actual_type))
+        f"Date should be either a subclass of 'datetime.date', string or bytes! But is: {actual_type} instead")
 
 
 def create_tns_column_mapping(subject_import_data: SubjectImportData):
diff --git a/smash/web/tests/models/test_mail_template.py b/smash/web/tests/models/test_mail_template.py
index 6d8984208dfb66d7677bc1cc6de783426653fa41..c00cf0fa966af8724ecffa5b53c3201c4aa6cba9 100644
--- a/smash/web/tests/models/test_mail_template.py
+++ b/smash/web/tests/models/test_mail_template.py
@@ -187,7 +187,7 @@ class MailTemplateModelTests(TestCase):
 
         for entry in get_mails_template_subject_tags():
             key = entry[0]
-            self.assertIsNotNone(replacements.get(key, None), "Value for field {} does not exist".format(key))
+            self.assertIsNotNone(replacements.get(key, None), f"Value for field {key} does not exist")
 
     def test_valid_appointment_replacement(self):
         appointment = create_appointment()
@@ -269,7 +269,7 @@ class MailTemplateModelTests(TestCase):
 
         if count_found != len(needles):
             for i, text in enumerate(needles):
-                self.assertTrue(founds[i], "{} was not found in the generated Word document".format(text))
+                self.assertTrue(founds[i], f"{text} was not found in the generated Word document")
 
     def test_get_generic_replacements(self):
         worker = create_worker()
@@ -312,7 +312,7 @@ class MailTemplateModelTests(TestCase):
 
         replacements = MailTemplate.get_subject_replacements(subject)
         key = get_field_id(field)
-        self.assertEqual(replacements.get(key, None), "test val", "Wrong value for field {}".format(key))
+        self.assertEqual(replacements.get(key, None), "test val", f"Wrong value for field {key}")
 
     def test_replacement_for_custom_field_with_no_subject(self):
         study = Study.objects.get(id=GLOBAL_STUDY_ID)
@@ -322,7 +322,7 @@ class MailTemplateModelTests(TestCase):
                                                        type=CUSTOM_FIELD_TYPE_TEXT, possible_values="")
         replacements = MailTemplate.get_subject_replacements()
         key = get_field_id(field)
-        self.assertIsNone(replacements.get(key, None), "Wrong value for field {}".format(key))
+        self.assertIsNone(replacements.get(key, None), f"Wrong value for field {key}")
 
     def test_get_field_id(self):
         field = CustomStudySubjectField.objects.create(study=Study.objects.get(id=GLOBAL_STUDY_ID),
diff --git a/smash/web/tests/models/test_study_subject.py b/smash/web/tests/models/test_study_subject.py
index 87d816e1f089a9d8c5ac876c19c5912d1f680ba9..5bbd8a719a52ba005354e78f01fa3b4279210ea3 100644
--- a/smash/web/tests/models/test_study_subject.py
+++ b/smash/web/tests/models/test_study_subject.py
@@ -153,8 +153,7 @@ class SubjectModelTests(TestCase):
 
     def test_sort_matched_screening_first_bad_number(self):
         subject_id = 2
-        screening_number = 'L-0/0{first_id}; E-00{second_id}; F-0/1{third_id}'.format(
-            first_id=subject_id, second_id=subject_id, third_id=subject_id)
+        screening_number = f'L-0/0{subject_id}; E-00{subject_id}; F-0/1{subject_id}'
 
         subject = create_study_subject_with_multiple_screening_numbers(
             subject_id=subject_id, screening_number=screening_number)
diff --git a/smash/web/tests/test_office_availability.py b/smash/web/tests/test_office_availability.py
index c95b28551e203c4a75844ade9340ddd1d2d12e49..f52b2764d61882d760553c7c93d07fca8caca3ba 100644
--- a/smash/web/tests/test_office_availability.py
+++ b/smash/web/tests/test_office_availability.py
@@ -26,7 +26,7 @@ class OfficeAvailabilityTest(TestCase):
 
         first_name = 'âêîôûŵŷäëïöüẅÿà'
         last_name = 'èìòùẁỳáéíóúẃýćńóśźżąę'
-        office_availability = OfficeAvailability('{} {}'.format(first_name, last_name),
+        office_availability = OfficeAvailability(f'{first_name} {last_name}',
                                                  start=start_date, end=end_date, office_start='8:00',
                                                  office_end='18:00')
 
@@ -138,7 +138,7 @@ class OfficeAvailabilityTest(TestCase):
 
         first_name = 'âêîôûŵŷäëïöüẅÿà'
         last_name = 'èìòùẁỳáéíóúẃýćńóśźżąę'
-        office_availability = OfficeAvailability('{} {}'.format(first_name, last_name),
+        office_availability = OfficeAvailability(f'{first_name} {last_name}',
                                                  start=start_date, end=end_date, office_start='8:00',
                                                  office_end='18:00')
 
@@ -180,7 +180,7 @@ class OfficeAvailabilityTest(TestCase):
 
         first_name = 'âêîôûŵŷäëïöüẅÿà'
         last_name = 'èìòùẁỳáéíóúẃýćńóśźżąę'
-        office_availability = OfficeAvailability('{} {}'.format(first_name, last_name),
+        office_availability = OfficeAvailability(f'{first_name} {last_name}',
                                                  start=start_date, end=end_date, office_start='8:00',
                                                  office_end='18:00')
 
diff --git a/smash/web/tests/view/test_appointments.py b/smash/web/tests/view/test_appointments.py
index dd71482a93e90fa956e67a13cb78755e509e9b7a..4f63a0a46a0a1ec18105a1f7489a1621fc6621d6 100644
--- a/smash/web/tests/view/test_appointments.py
+++ b/smash/web/tests/view/test_appointments.py
@@ -169,7 +169,7 @@ class AppointmentsViewTests(LoggedInTestCase):
         form_data = {}
         for key, value in list(form_appointment.initial.items()):
             if value is not None:
-                form_data['appointment-{}'.format(key)] = value
+                form_data[f'appointment-{key}'] = value
         response = self.client.post(
             reverse('web.views.appointment_edit', kwargs={'appointment_id': appointment.id}), data=form_data)
 
@@ -184,7 +184,7 @@ class AppointmentsViewTests(LoggedInTestCase):
         form_data = {'_continue': True}
         for key, value in list(form_appointment.initial.items()):
             if value is not None:
-                form_data['appointment-{}'.format(key)] = value
+                form_data[f'appointment-{key}'] = value
         response = self.client.post(reverse('web.views.appointment_edit', kwargs={'appointment_id': appointment.id}),
                                     data=form_data, follow=True)
 
@@ -199,7 +199,7 @@ class AppointmentsViewTests(LoggedInTestCase):
         form_data = {}
         for key, value in list(form_appointment.initial.items()):
             if value is not None:
-                form_data['appointment-{}'.format(key)] = format_form_field(value)
+                form_data[f'appointment-{key}'] = format_form_field(value)
         form_data['appointment-status'] = Appointment.APPOINTMENT_STATUS_FINISHED
         self.client.post(reverse('web.views.appointment_edit', kwargs={'appointment_id': appointment.id}),
                          data=form_data)
@@ -281,11 +281,11 @@ class AppointmentsViewTests(LoggedInTestCase):
         form_subject = SubjectEditForm(instance=subject.subject, prefix="subject")
         form_data = {}
         for key, value in list(form_appointment.initial.items()):
-            form_data['appointment-{}'.format(key)] = format_form_field(value)
+            form_data[f'appointment-{key}'] = format_form_field(value)
         for key, value in list(form_study_subject.initial.items()):
-            form_data['study-subject-{}'.format(key)] = format_form_field(value)
+            form_data[f'study-subject-{key}'] = format_form_field(value)
         for key, value in list(form_subject.initial.items()):
-            form_data['subject-{}'.format(key)] = format_form_field(value)
+            form_data[f'subject-{key}'] = format_form_field(value)
         form_data["study-subject-referral_letter"] = SimpleUploadedFile("file.txt", b"file_content")
         return form_data
 
diff --git a/smash/web/tests/view/test_contact_attempt.py b/smash/web/tests/view/test_contact_attempt.py
index 424da3ca73ca6b7815f8fb4725e7b226a757ba7f..36aa653e95f4719e7915b4df76cadb0bf8bc5a26 100644
--- a/smash/web/tests/view/test_contact_attempt.py
+++ b/smash/web/tests/view/test_contact_attempt.py
@@ -15,8 +15,8 @@ class ContactAttemptViewTests(LoggedInTestCase):
     def test_contact_attempt_add_get(self):
         subject = create_study_subject()
         response = self.client.get(reverse('web.views.contact_add', kwargs={'subject_id': subject.id}))
-        self.assertContains(response, 'selected>{}'.format(self.worker), 1)
-        self.assertContains(response, 'selected>{}'.format(subject), 1)
+        self.assertContains(response, f'selected>{self.worker}', 1)
+        self.assertContains(response, f'selected>{subject}', 1)
 
     def test_contact_attempt_add_post_valid(self):
         subject = create_study_subject()
diff --git a/smash/web/tests/view/test_statistics.py b/smash/web/tests/view/test_statistics.py
index f6196f39712adf7588bfb9ae7a5ef436abe03c44..9baeb389c6948aaacf1e3daec660cdc99c74b24a 100644
--- a/smash/web/tests/view/test_statistics.py
+++ b/smash/web/tests/view/test_statistics.py
@@ -16,7 +16,7 @@ class TestStatisticsView(LoggedInTestCase):
         self.assertEqual(response.status_code, 200)
         current_month = timezone.now().month - 1 or 12
         content = response.content.decode('utf8')
-        self.assertIn('<option value="{}" selected>'.format(current_month), content)
+        self.assertIn(f'<option value="{current_month}" selected>', content)
         response = self.client.get(url, {"month": 10, "year": 2017, "subject_type": -1, "visit": -1})
         content = response.content.decode('utf8')
         self.assertIn('<option value="10" selected>October', content)
diff --git a/smash/web/tests/view/test_study.py b/smash/web/tests/view/test_study.py
index 798ab38ebcfaa423067045278a844eea13ba8b3a..785131858b0513a6ab18b590365c8ea06b2cd013 100644
--- a/smash/web/tests/view/test_study.py
+++ b/smash/web/tests/view/test_study.py
@@ -82,9 +82,9 @@ class StudyViewTests(LoggedInTestCase):
 
         form_data = {}
         for key, value in list(study_form.initial.items()):
-            form_data['study-{}'.format(key)] = format_form_field(value)
+            form_data[f'study-{key}'] = format_form_field(value)
         for key, value in list(notifications_form.initial.items()):
-            form_data['notifications-{}'.format(key)] = format_form_field(value)
+            form_data[f'notifications-{key}'] = format_form_field(value)
         for key, value in list(study_columns_form.initial.items()):
-            form_data['columns-{}'.format(key)] = format_form_field(value)
+            form_data[f'columns-{key}'] = format_form_field(value)
         return form_data
diff --git a/smash/web/tests/view/test_study_subject_list.py b/smash/web/tests/view/test_study_subject_list.py
index ca7a19e2b20b0bc18d4832e2388e2999b910062e..a94198369a09e46771e3940c4651594bc6e3e8e7 100644
--- a/smash/web/tests/view/test_study_subject_list.py
+++ b/smash/web/tests/view/test_study_subject_list.py
@@ -50,9 +50,9 @@ class StudySubjectListViewTests(LoggedInTestCase):
 
         form_data = {}
         for key, value in list(list_form.initial.items()):
-            form_data['list-{}'.format(key)] = format_form_field(value)
+            form_data[f'list-{key}'] = format_form_field(value)
         for key, value in list(study_subject_columns_form.initial.items()):
-            form_data['study_subject-{}'.format(key)] = format_form_field(value)
+            form_data[f'study_subject-{key}'] = format_form_field(value)
         for key, value in list(subject_columns_form.initial.items()):
-            form_data['subject_columns_form-{}'.format(key)] = format_form_field(value)
+            form_data[f'subject_columns_form-{key}'] = format_form_field(value)
         return form_data
diff --git a/smash/web/tests/view/test_subjects.py b/smash/web/tests/view/test_subjects.py
index ca946bf9701813a399c1bf11917c1d26b725f16f..ffa66975d88f3c19b684aa65b2c0fbfd6b410320 100644
--- a/smash/web/tests/view/test_subjects.py
+++ b/smash/web/tests/view/test_subjects.py
@@ -206,9 +206,9 @@ class SubjectsViewTests(LoggedInTestCase):
         form_subject = SubjectEditForm(instance=instance.subject, prefix="subject")
         form_data = {}
         for key, value in list(form_study_subject.initial.items()):
-            form_data['study_subject-{}'.format(key)] = format_form_field(value)
+            form_data[f'study_subject-{key}'] = format_form_field(value)
         for key, value in list(form_subject.initial.items()):
-            form_data['subject-{}'.format(key)] = format_form_field(value)
+            form_data[f'subject-{key}'] = format_form_field(value)
         form_data["study_subject-referral_letter"] = SimpleUploadedFile("file.txt", b"file_content")
         return form_data
 
@@ -217,9 +217,9 @@ class SubjectsViewTests(LoggedInTestCase):
         form_subject = SubjectAddForm(prefix="subject")
         form_data = {}
         for key, value in list(form_study_subject.initial.items()):
-            form_data['study_subject-{}'.format(key)] = format_form_field(value)
+            form_data[f'study_subject-{key}'] = format_form_field(value)
         for key, value in list(form_subject.initial.items()):
-            form_data['subject-{}'.format(key)] = format_form_field(value)
+            form_data[f'subject-{key}'] = format_form_field(value)
         self.add_valid_form_data_for_subject_add(form_data)
         form_data["study_subject-default_location"] = get_test_location().id
         return form_data
diff --git a/smash/web/tests/view/test_voucher_type_price.py b/smash/web/tests/view/test_voucher_type_price.py
index e1d7b1e158447f4b614ceef3d6a0af06421260a2..2f3ec7ed841e4e768f030ce99caedecbe6168bfd 100644
--- a/smash/web/tests/view/test_voucher_type_price.py
+++ b/smash/web/tests/view/test_voucher_type_price.py
@@ -48,7 +48,7 @@ class VoucherTypePriceViewTests(LoggedInTestCase):
         form_data = {}
         for key, value in list(form.initial.items()):
             if value is not None:
-                form_data['{}'.format(key)] = format_form_field(value)
+                form_data[f'{key}'] = format_form_field(value)
         form_data['price'] = 90.50
 
         url = reverse('web.views.voucher_type_price_edit',
diff --git a/smash/web/utils.py b/smash/web/utils.py
index 9315662d9f724544abb9645e0a90a81a0aeefcb2..544aa884517ada9a712b312b098563ac60a1aefc 100644
--- a/smash/web/utils.py
+++ b/smash/web/utils.py
@@ -19,8 +19,7 @@ def get_deleted_objects(objs: List[models.Model]):
     #
     def format_callback(obj):
         opts = obj._meta
-        no_edit_link = '%s: %s' % (capfirst(opts.verbose_name),
-                                   force_text(obj))
+        no_edit_link = f'{capfirst(opts.verbose_name)}: {force_text(obj)}'
         return no_edit_link
         #
 
diff --git a/smash/web/views/appointment.py b/smash/web/views/appointment.py
index 43495dba8508a557253f457fbbb6399e661be27f..d078f89ac3713f3aa9b3d8f0d8670d070dc5c568 100644
--- a/smash/web/views/appointment.py
+++ b/smash/web/views/appointment.py
@@ -49,7 +49,7 @@ def appointment_add(request: HttpRequest, visit_id: int = None) -> HttpResponse:
             return redirect('web.views.subject_visit_details', subject_id=visit.subject.id)
         if not visit.subject.can_schedule():
             messages.error(request,
-                           "Appointment cannot be added because the subject status is: {}".format(visit.subject.status))
+                           f"Appointment cannot be added because the subject status is: {visit.subject.status}")
             return redirect('web.views.subject_visit_details', subject_id=visit.subject.id)
     else:
         visit_start = datetime.datetime.today().strftime("%Y-%m-%d")
@@ -64,7 +64,7 @@ def appointment_add(request: HttpRequest, visit_id: int = None) -> HttpResponse:
             else:
                 return redirect('web.views.visit_details', visit_id)
         else:
-            messages.add_message(request, messages.ERROR, '{}'.format(form.non_field_errors()))
+            messages.add_message(request, messages.ERROR, f'{form.non_field_errors()}')
     else:
         form = AppointmentAddForm(user=request.user, visit=visit)
 
@@ -83,8 +83,7 @@ def appointment_edit(request, appointment_id: int):
 
     if the_appointment.visit is not None and the_appointment.visit.subject is not None:
         if not the_appointment.visit.subject.can_schedule():
-            messages.error(request, "Appointment cannot be edited because the subject status is: {}".format(
-                the_appointment.visit.subject.status))
+            messages.error(request, f"Appointment cannot be edited because the subject status is: {the_appointment.visit.subject.status}")
             return redirect('web.views.subject_visit_details', subject_id=the_appointment.visit.subject.id)
 
     if request.method == 'POST':
diff --git a/smash/web/views/mails.py b/smash/web/views/mails.py
index 8808b0ce9bf83f535600977cc01eb873e4c203b8..f1a42dddba7db8aeb610f379ef77dd1a1116fe59 100644
--- a/smash/web/views/mails.py
+++ b/smash/web/views/mails.py
@@ -116,7 +116,7 @@ def generate(request: HttpRequest, mail_template_id: int, instance_id: int) -> H
     stream.seek(0)
     response = HttpResponse(FileWrapper(stream), content_type=MIMETYPE_DOCX)
     response['Content-Length'] = file_size
-    response['Content-Disposition'] = 'attachment; filename={}.docx'.format(mail_template.name)
+    response['Content-Disposition'] = f'attachment; filename={mail_template.name}.docx'
     return response
 
 
diff --git a/smash/web/views/password.py b/smash/web/views/password.py
index 657d069a8fd0ea15e5331c3cb5719b69fcfea775..584224ca6a165e1243fb44b389e5a02d43bec59b 100644
--- a/smash/web/views/password.py
+++ b/smash/web/views/password.py
@@ -13,7 +13,7 @@ def change_password(request):
         if form.is_valid():
             user = form.save()
             update_session_auth_hash(request, user)
-            messages.success(request, 'The password for {} was successfully updated!'.format(request.user))
+            messages.success(request, f'The password for {request.user} was successfully updated!')
             return redirect('web.views.workers')
         else:
             messages.error(request, 'Please correct the error below.')
diff --git a/smash/web/views/subject.py b/smash/web/views/subject.py
index b24ef431a218c7d40954104e16e50950a453a41f..1ee93323a1b76dc30a9e2da4dbc4f405ee235c73 100644
--- a/smash/web/views/subject.py
+++ b/smash/web/views/subject.py
@@ -156,10 +156,7 @@ def subject_edit(request, subject_id):
                                modification_author=worker,
                                previous_value=old_type,
                                new_value=study_subject_form.cleaned_data['type'],
-                               modification_description='Worker "{}" changed study subject "{}" from "{}" to "{}"'
-                               .format(
-                                   worker,
-                                   study_subject.subject, old_value, new_value),
+                               modification_description=f'Worker "{worker}" changed study subject "{study_subject.subject}" from "{old_type}" to "{new_value}"',
                                modified_field='type',
                                request_path=request.path,
                                request_ip_addr=ip
@@ -173,8 +170,7 @@ def subject_edit(request, subject_id):
                                modification_author=worker,
                                previous_value=was_dead,
                                new_value=True,
-                               modification_description='Worker "{}" marks subject "{}" as dead'.format(
-                                   worker, study_subject.subject),
+                               modification_description=f'Worker "{worker}" marks subject "{study_subject.subject}" as dead',
                                modified_field='dead',
                                request_path=request.path,
                                request_ip_addr=ip
@@ -189,9 +185,8 @@ def subject_edit(request, subject_id):
                                modification_author=worker,
                                previous_value=was_resigned,
                                new_value=True,
-                               modification_description='Worker "{}" marks study subject "{}" as resigned '
-                                                        'from study "{}"'.format(worker, study_subject.nd_number,
-                                                                                 study_subject.study),
+                               modification_description=f'Worker "{worker}" marks study subject "{study_subject.nd_number}" as resigned '
+                                                        f'from study "{study_subject.study}"',
                                modified_field='resigned',
                                request_path=request.path,
                                request_ip_addr=ip
diff --git a/smash/web/views/uploaded_files.py b/smash/web/views/uploaded_files.py
index de6f7c6b1e2901385f832f13ed014c687ba983ed..04b6ee08cc9c9e3834451b362829d496abd3f103 100644
--- a/smash/web/views/uploaded_files.py
+++ b/smash/web/views/uploaded_files.py
@@ -19,5 +19,5 @@ def download(request):
     if request.GET and request.GET.get('file'):
         path = FILE_STORAGE.location + "/" + request.GET.get('file')
         response = HttpResponse(FileWrapper(open(path, 'rb')), content_type='application/force-download')
-        response['Content-Disposition'] = 'attachment; filename=%s' % path_to_filename(path)
+        response['Content-Disposition'] = f'attachment; filename={path_to_filename(path)}'
         return response
diff --git a/smash/web/views/virus_mail.py b/smash/web/views/virus_mail.py
index 56ee8f8dafaf1efb53fa49984e059182f78b7a99..98064be697f30d6c00a30c95ea7677ea834900bf 100644
--- a/smash/web/views/virus_mail.py
+++ b/smash/web/views/virus_mail.py
@@ -21,12 +21,12 @@ def count_subjects(date_when: datetime, status: str) -> int:
     str_date = date_when.strftime("%Y-%m-%d")
     for i in range(0, 10):
         fields = CustomStudySubjectField.objects.filter(study_id=GLOBAL_STUDY_ID,
-                                                        name='Visit {} RT-PCR collection date'.format(i)).all()
+                                                        name=f'Visit {i} RT-PCR collection date').all()
         collect_field = None
         if len(fields) > 0:
             collect_field = fields[0]
         fields = CustomStudySubjectField.objects.filter(study_id=GLOBAL_STUDY_ID,
-                                                        name__contains='Virus {} RT-PCR'.format(i)).all()
+                                                        name__contains=f'Virus {i} RT-PCR').all()
         status_field = None
         if len(fields) > 0:
             status_field = fields[0]
@@ -56,7 +56,7 @@ def get_subject_statistics():
 def create_statistic_email_content(data, title):
     email_body = "<h1>" + title + "</h1>"
 
-    email_body += '<b>Date: {}</b>'.format(datetime.datetime.now().strftime('%d.%m.%Y')) + "</br></br>"
+    email_body += f"<b>Date: {datetime.datetime.now().strftime('%d.%m.%Y')}</b>" + "</br></br>"
 
     email_body += "In the past 24 hours " + str(data["total"]) + " donors were tested</br></br>"