diff --git a/core/admin.py b/core/admin.py
index a2e9f295ca1e3cb3e5c3afd5fef9ec0cc66a6443..79001a88ee94f003a380a2964ed9369290d2b476 100644
--- a/core/admin.py
+++ b/core/admin.py
@@ -1,8 +1,8 @@
 from django.contrib import admin
 from django.contrib.auth.models import Group
 
-from core.models import (ExamType, Feedback, Reviewer, Student, Submission,
-                         SubmissionType, Test, Tutor, UserAccount)
+from core.models import (ExamType, Feedback, StudentInfo, Submission,
+                         SubmissionType, Test, UserAccount)
 
 # Stuff we needwant
 admin.site.register(UserAccount)
@@ -11,9 +11,7 @@ admin.site.register(Feedback)
 admin.site.register(Test)
 admin.site.register(ExamType)
 admin.site.register(Submission)
-admin.site.register(Reviewer)
-admin.site.register(Student)
-admin.site.register(Tutor)
+admin.site.register(StudentInfo)
 
 # ... and stuff we don't needwant
 admin.site.unregister(Group)
diff --git a/core/migrations/0007_auto_20180105_1136.py b/core/migrations/0007_auto_20180105_1136.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b3aa7ee3d0585817b5afe1a30a231f57841785d
--- /dev/null
+++ b/core/migrations/0007_auto_20180105_1136.py
@@ -0,0 +1,41 @@
+# Generated by Django 2.0 on 2018-01-05 11:36
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0006_auto_20180104_2001'),
+    ]
+
+    operations = [
+        migrations.RenameModel(
+            old_name='Student',
+            new_name='StudentInfo',
+        ),
+        migrations.RemoveField(
+            model_name='reviewer',
+            name='user',
+        ),
+        migrations.RemoveField(
+            model_name='tutor',
+            name='user',
+        ),
+        migrations.RemoveField(
+            model_name='feedback',
+            name='of_reviewer',
+        ),
+        migrations.AddField(
+            model_name='useraccount',
+            name='role',
+            field=models.CharField(choices=[('Student', 'student'), ('Tutor', 'tutor'), ('Reviewer', 'reviewer')], default='Student', max_length=50),
+            preserve_default=False,
+        ),
+        migrations.DeleteModel(
+            name='Reviewer',
+        ),
+        migrations.DeleteModel(
+            name='Tutor',
+        ),
+    ]
diff --git a/core/models.py b/core/models.py
index 1f7d19274a567ae7864806d15039ce25c11e8054..f2268ed945cd64a993ee96e391ce98f01c28ac83 100644
--- a/core/models.py
+++ b/core/models.py
@@ -149,43 +149,48 @@ class UserAccount(AbstractUser):
     fullname = models.CharField('full name', max_length=70, blank=True)
     is_admin = models.BooleanField(default=False)
 
-    def get_associated_user(self) -> models.Model:
-        """ Returns the user type that is associated with this user obj """
-        return \
-            (hasattr(self, 'student') and self.student) or \
-            (hasattr(self, 'reviewer') and self.reviewer) or \
-            (hasattr(self, 'tutor') and self.tutor)
+    STUDENT = 'Student'
+    TUTOR = 'Tutor'
+    REVIEWER = 'Reviewer'
+
+    ROLE_CHOICES = (
+        (STUDENT, 'student'),
+        (TUTOR, 'tutor'),
+        (REVIEWER, 'reviewer')
+    )
 
-    def is_reviewer(self):
-        return hasattr(self, 'reviewer')
-
-    def is_tutor(self):
-        return hasattr(self, 'tutor')
+    role = models.CharField(max_length=50, choices=ROLE_CHOICES)
 
     def is_student(self):
-        return hasattr(self, 'student')
+        return self.role == 'Student'
 
+    def is_tutor(self):
+        return self.role == 'Tutor'
 
-class Tutor(models.Model):
-    user = models.OneToOneField(get_user_model(),
-                                on_delete=models.CASCADE,
-                                related_name='tutor')
+    def is_reviewer(self):
+        return self.role == 'Reviewer'
 
     def get_feedback_count(self) -> int:
         return self.feedback_list.count()
 
+    @classmethod
+    def get_students(cls):
+        return cls.objects.filter(role=cls.STUDENT)
 
-class Reviewer(models.Model):
-    user = models.OneToOneField(get_user_model(),
-                                on_delete=models.CASCADE,
-                                related_name='reviewer')
+    @classmethod
+    def get_tutors(cls):
+        return cls.objects.filter(role=cls.TUTOR)
+
+    @classmethod
+    def get_reviewers(cls):
+        return cls.objects.filter(role=cls.REVIEWER)
 
 
-class Student(models.Model):
+class StudentInfo(models.Model):
     """
-    The student model includes all information of a student, that we got from
-    the E-Learning output, along with some useful classmethods that provide
-    specially annotated QuerySets.
+    The StudentInfo model includes all information of a student, that we got
+    from the E-Learning output, along with some useful classmethods that
+    provide specially annotated QuerySets.
 
     Information like email (if given), and the username are stored in the
     associated user model.
@@ -331,7 +336,7 @@ class Submission(models.Model):
         on_delete=models.PROTECT,
         related_name='submissions')
     student = models.ForeignKey(
-        Student,
+        StudentInfo,
         on_delete=models.CASCADE,
         related_name='submissions')
 
@@ -389,12 +394,6 @@ class Feedback(models.Model):
         related_name='feedback_list',
         blank=True,
         null=True)
-    of_reviewer = models.ForeignKey(
-        Reviewer,
-        on_delete=models.SET_NULL,
-        related_name='reviewed_submissions',
-        blank=True,
-        null=True)
 
     # how was this feedback created
     (
diff --git a/core/permissions.py b/core/permissions.py
index 5466fa2357f5f31a85085a172090934985e70f03..e88aed697a0e5500f6f8e5f376e2d9dc8f1fae12 100644
--- a/core/permissions.py
+++ b/core/permissions.py
@@ -4,26 +4,24 @@ from django.http import HttpRequest
 from django.views import View
 from rest_framework import permissions
 
-from core.models import Reviewer, Student, Tutor
 
 log = logging.getLogger(__name__)
 
 
-class IsUserGenericPermission(permissions.BasePermission):
+class IsUserRoleGenericPermission(permissions.BasePermission):
     """ Generic class that encapsulates how to identify someone
     as a member of a user Group """
 
     def has_permission(self, request: HttpRequest, view: View) -> bool:
         """ required by BasePermission. Check if user is instance of any
         of the models provided in class' models attribute """
-        assert self.models is not None, (
-            "'%s' has to include a `models` attribute"
+        assert self.roles is not None, (
+            "'%s' has to include a `roles` attribute"
             % self.__class__.__name__
         )
 
         user = request.user
-        is_authorized = user.is_authenticated and any(isinstance(
-            user.get_associated_user(), models) for models in self.models)
+        is_authorized = user.is_authenticated and user.role in self.roles
 
         if not is_authorized:
             log.warn('User "%s" has no permission to view %s',
@@ -32,21 +30,21 @@ class IsUserGenericPermission(permissions.BasePermission):
         return is_authorized
 
 
-class IsStudent(IsUserGenericPermission):
+class IsStudent(IsUserRoleGenericPermission):
     """ Has student permissions """
-    models = (Student,)
+    roles = ('Student', )
 
 
-class IsReviewer(IsUserGenericPermission):
+class IsReviewer(IsUserRoleGenericPermission):
     """ Has reviewer permissions """
-    models = (Reviewer,)
+    roles = ('Reviewer', )
 
 
-class IsTutor(IsUserGenericPermission):
+class IsTutor(IsUserRoleGenericPermission):
     """ Has tutor permissions """
-    models = (Tutor,)
+    roles = ('Tutor', )
 
 
-class IsTutorOrReviewer(IsUserGenericPermission):
+class IsTutorOrReviewer(IsUserRoleGenericPermission):
     """ Has tutor or reviewer permissions """
-    models = (Tutor, Reviewer,)
+    roles = ('Tutor', 'Reviewer')
diff --git a/core/serializers.py b/core/serializers.py
index cd017afe64c21cfb45a7d12a46d5d3a5e85834bb..18b7f14233b234bec04b853500c6c912ed39b294 100644
--- a/core/serializers.py
+++ b/core/serializers.py
@@ -6,8 +6,10 @@ from django.core.exceptions import ObjectDoesNotExist
 from drf_dynamic_fields import DynamicFieldsMixin
 from rest_framework import serializers
 
-from core.models import (ExamType, Feedback, GeneralTaskSubscription, Student,
-                         Submission, SubmissionType, Tutor,
+from core import models
+from core.models import (ExamType, Feedback, GeneralTaskSubscription,
+                         StudentInfo,
+                         Submission, SubmissionType,
                          TutorSubmissionAssignment)
 from util.factories import GradyUserFactory
 
@@ -94,14 +96,14 @@ class SubmissionSerializer(DynamicFieldsModelSerializer):
                   'feedback', 'score', 'full_score')
 
 
-class StudentSerializer(DynamicFieldsModelSerializer):
+class StudentInfoSerializer(DynamicFieldsModelSerializer):
     name = serializers.ReadOnlyField(source='user.fullname')
     user = serializers.ReadOnlyField(source='user.username')
     exam = ExamSerializer()
     submissions = SubmissionSerializer(many=True)
 
     class Meta:
-        model = Student
+        model = StudentInfo
         fields = ('name', 'user', 'exam', 'submissions')
 
 
@@ -115,29 +117,28 @@ class SubmissionNoTextFieldsSerializer(DynamicFieldsModelSerializer):
         fields = ('type', 'score', 'full_score')
 
 
-class StudentSerializerForListView(DynamicFieldsModelSerializer):
+class StudentInfoSerializerForListView(DynamicFieldsModelSerializer):
     name = serializers.ReadOnlyField(source='user.fullname')
     user = serializers.ReadOnlyField(source='user.username')
     exam = serializers.ReadOnlyField(source='exam.module_reference')
     submissions = SubmissionNoTextFieldsSerializer(many=True)
 
     class Meta:
-        model = Student
+        model = StudentInfo
         fields = ('name', 'user', 'exam', 'submissions')
 
 
 class TutorSerializer(DynamicFieldsModelSerializer):
-    username = serializers.CharField(source='user.username')
     feedback_count = serializers.IntegerField(source='get_feedback_count',
                                               read_only=True)
 
-    def create(self, validated_data) -> Tutor:
+    def create(self, validated_data) -> models.UserAccount:
         log.info("Crating tutor from data %s", validated_data)
         return user_factory.make_tutor(
-            username=validated_data['user']['username'])
+            username=validated_data['username'])
 
     class Meta:
-        model = Tutor
+        model = models.UserAccount
         fields = ('username', 'feedback_count')
 
 
diff --git a/core/tests/test_access_rights.py b/core/tests/test_access_rights.py
index 9c22248b907e106d7a78448fb011655a04b5bb45..8a636dbf0191a29d4f98828310859b4d3508a49c 100644
--- a/core/tests/test_access_rights.py
+++ b/core/tests/test_access_rights.py
@@ -29,17 +29,17 @@ class AccessRightsOfStudentAPIViewTests(APITestCase):
         self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
 
     def test_tutor_has_no_access(self):
-        force_authenticate(self.request, user=self.tutor.user)
+        force_authenticate(self.request, user=self.tutor)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_reviewer_has_no_access(self):
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_student_is_authorized(self):
-        force_authenticate(self.request, user=self.student.user)
+        force_authenticate(self.request, user=self.student)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
 
@@ -64,17 +64,17 @@ class AccessRightsOfTutorAPIViewTests(APITestCase):
         self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
 
     def test_student_has_no_access(self):
-        force_authenticate(self.request, user=self.student.user)
+        force_authenticate(self.request, user=self.student)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_tutor_has_no_access(self):
-        force_authenticate(self.request, user=self.tutor.user)
+        force_authenticate(self.request, user=self.tutor)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_reviewer_has_access(self):
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
 
@@ -100,17 +100,17 @@ class AccessRightsOfStudentReviewerAPIViewTest(APITestCase):
         self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
 
     def test_student_has_no_access(self):
-        force_authenticate(self.request, user=self.student.user)
+        force_authenticate(self.request, user=self.student)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_tutor_has_no_access(self):
-        force_authenticate(self.request, user=self.tutor.user)
+        force_authenticate(self.request, user=self.tutor)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_reviewer_has_access(self):
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
 
@@ -134,16 +134,16 @@ class AccessRightsOfExamTypeAPIViewTest(APITestCase):
         self.view = ExamApiViewSet.as_view({'get': 'list'})
 
     def test_student_has_no_access(self):
-        force_authenticate(self.request, user=self.student.user)
+        force_authenticate(self.request, user=self.student)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_tutor_has_no_access(self):
-        force_authenticate(self.request, user=self.tutor.user)
+        force_authenticate(self.request, user=self.tutor)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
 
     def test_reviewer_has_access(self):
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         response = self.view(self.request)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
diff --git a/core/tests/test_examlist.py b/core/tests/test_examlist.py
index f1e99b2d0182624576c3079149564a481317b185..b5be17ccb0f15831591d7f0619fc13973648b2d6 100644
--- a/core/tests/test_examlist.py
+++ b/core/tests/test_examlist.py
@@ -24,7 +24,7 @@ class ExamListTest(APITestCase):
                                                 total_score=90,
                                                 pass_score=45)
         force_authenticate(self.request,
-                           self.user_factory.make_reviewer().user)
+                           self.user_factory.make_reviewer())
         self.view = ExamApiViewSet.as_view({'get': 'list'})
         self.response = self.view(self.request)
 
diff --git a/core/tests/test_factory_and_feedback.py b/core/tests/test_factory_and_feedback.py
index 42ed4a4e2e1434cc1e4d63898c50a9ae75b153fd..5b5828901c33fcf9f2393e48c76bef4f1a884686 100644
--- a/core/tests/test_factory_and_feedback.py
+++ b/core/tests/test_factory_and_feedback.py
@@ -1,6 +1,7 @@
 from django.test import TestCase
 
-from core.models import Reviewer, Student, Tutor
+from core import models
+from core.models import StudentInfo
 from util.factories import GradyUserFactory
 
 
@@ -10,39 +11,28 @@ class FactoryTestCase(TestCase):
 
     def test_make_student(self):
 
-        student = self.factory.make_student()
+        user = self.factory.make_student()
 
-        self.assertEqual(Student.objects.count(), 1)
-        self.assertEqual(student.exam, None)
-        self.assertEqual(len(str(student.matrikel_no)), 8)
+        self.assertEqual(StudentInfo.objects.count(), 1)
+        self.assertEqual(user.student.exam, None)
+        self.assertEqual(len(str(user.student.matrikel_no)), 8)
 
     def test_can_create_reviewer(self):
-        self.assertTrue(isinstance(self.factory.make_reviewer(), Reviewer))
+        self.assertTrue(isinstance(self.factory.make_reviewer(),
+                                   models.UserAccount))
 
     def test_reviewer_appears_in_query_set(self):
-        self.assertIn(self.factory.make_reviewer(), Reviewer.objects.all())
+        self.assertIn(self.factory.make_reviewer(),
+                      models.UserAccount.objects.all())
 
     def test_can_create_tutor(self):
-        self.assertIn(self.factory.make_tutor(), Tutor.objects.all())
+        self.assertIn(self.factory.make_tutor(),
+                      models.UserAccount.objects.all())
 
-    def test_can_create_student(self):
-        self.assertIn(self.factory.make_student(), Student.objects.all())
+    def test_can_create_student_user(self):
+        self.assertIn(self.factory.make_student(),
+                      models.UserAccount.objects.all())
 
-
-class AccountsTestCase(TestCase):
-
-    factory = GradyUserFactory()
-
-    def _test_user_obj_returns_correct_type(self, maker):
-        model = maker()
-        user = model.user
-        self.assertEqual(user.get_associated_user(), model)
-
-    def test_user_obj_returns_correct_type_student(self):
-        self._test_user_obj_returns_correct_type(self.factory.make_student)
-
-    def test_user_obj_returns_correct_type_tutor(self):
-        self._test_user_obj_returns_correct_type(self.factory.make_tutor)
-
-    def test_user_obj_returns_correct_type_reviewer(self):
-        self._test_user_obj_returns_correct_type(self.factory.make_reviewer)
+    def test_can_create_student_info(self):
+        self.assertIn(self.factory.make_student().student,
+                      StudentInfo.objects.all())
diff --git a/core/tests/test_functional_views.py b/core/tests/test_functional_views.py
index 5a99c8b914092f3bc786f8d710b7d9ccec7852ac..7763b5c63f990a6e727c34f512f6014c6ce400e6 100644
--- a/core/tests/test_functional_views.py
+++ b/core/tests/test_functional_views.py
@@ -19,16 +19,16 @@ class GetUserRoleTest(APITestCase):
         self.request = self.factory.get(reverse('user-role'))
 
     def test_get_user_model_returns_student(self):
-        force_authenticate(self.request, user=self.student.user)
+        force_authenticate(self.request, user=self.student)
         response = get_user_role(self.request)
         self.assertEqual(response.data['role'], 'Student')
 
     def test_get_user_model_returns_tutor(self):
-        force_authenticate(self.request, user=self.tutor.user)
+        force_authenticate(self.request, user=self.tutor)
         response = get_user_role(self.request)
         self.assertEqual(response.data['role'], 'Tutor')
 
     def test_get_user_model_returns_reviewer(self):
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         response = get_user_role(self.request)
         self.assertEqual(response.data['role'], 'Reviewer')
diff --git a/core/tests/test_student_page.py b/core/tests/test_student_page.py
index 8bd9f349564483dea02e3c4ffc927f4ec65c8e4c..a3fa4f7ec19ff828643b7e3c7db6fbf9b42e4ce2 100644
--- a/core/tests/test_student_page.py
+++ b/core/tests/test_student_page.py
@@ -49,7 +49,7 @@ class StudentPageTests(APITestCase):
             }]
         })
 
-        self.student = self.test_data['students'][0]
+        self.student = self.test_data['students'][0].student
         self.tutor = self.test_data['tutors'][0]
         self.reviewer = self.test_data['reviewers'][0]
         self.submission = self.test_data['submissions'][0]
diff --git a/core/tests/test_student_reviewer_viewset.py b/core/tests/test_student_reviewer_viewset.py
index d486641ce9bcb6a9e936988ca2b4a5bd5d10e4fd..12500539a95a17754fb8988fd8722ffc8b15862a 100644
--- a/core/tests/test_student_reviewer_viewset.py
+++ b/core/tests/test_student_reviewer_viewset.py
@@ -48,14 +48,14 @@ class StudentPageTests(APITestCase):
             }]
         })
 
-        self.student = self.test_data['students'][0]
+        self.student = self.test_data['students'][0].student
         self.reviewer = self.test_data['reviewers'][0]
         self.submission = self.test_data['submissions'][0]
 
         self.request = self.factory.get(reverse('student-list'))
         self.view = StudentReviewerApiViewSet.as_view({'get': 'list'})
 
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         self.response = self.view(self.request)
 
     def test_can_access(self):
diff --git a/core/tests/test_submissiontypeview.py b/core/tests/test_submissiontypeview.py
index c1c7f4b096e2bebee299d89abefb04fbd254816f..a369a726b4b6b080fcd06fea89e2fb71b44acbb2 100644
--- a/core/tests/test_submissiontypeview.py
+++ b/core/tests/test_submissiontypeview.py
@@ -23,7 +23,7 @@ class SubmissionTypeViewTest(APITestCase):
                                       full_score=20,
                                       description='Whatever')
         force_authenticate(self.request,
-                           self.user_factory.make_reviewer().user)
+                           self.user_factory.make_reviewer())
         self.view = SubmissionTypeApiView.as_view({'get': 'list'})
         self.response = self.view(self.request)
 
diff --git a/core/tests/test_subscription_assignment_service.py b/core/tests/test_subscription_assignment_service.py
index d96aae0e56aa4edc50ee9d0e6a57b129edcb2fa9..20f81577d32c2c3998d68cb4b03261e22e2509dc 100644
--- a/core/tests/test_subscription_assignment_service.py
+++ b/core/tests/test_subscription_assignment_service.py
@@ -20,12 +20,14 @@ class GeneralTaskSubscriptionRandomTest(TestCase):
         self.submission_type = SubmissionType.objects.create(
             name='submission_01', full_score=14)
         self.submission_01 = Submission.objects.create(
-            type=self.submission_type, student=self.s1, text='I really failed')
+            type=self.submission_type, student=self.s1.student,
+            text='I really failed')
         self.submission_02 = Submission.objects.create(
-            type=self.submission_type, student=self.s2, text='I like apples')
+            type=self.submission_type, student=self.s2.student,
+            text='I like apples')
 
         self.subscription = GeneralTaskSubscription.objects.create(
-            owner=self.t.user, query_type=GeneralTaskSubscription.RANDOM)
+            owner=self.t, query_type=GeneralTaskSubscription.RANDOM)
 
     def test_subscription_gets_an_assignment(self):
         self.subscription._create_new_assignment_if_subscription_empty()
diff --git a/core/tests/test_tutor_api_endpoints.py b/core/tests/test_tutor_api_endpoints.py
index 8c8f59a5929bf73550d7db9bab80ba52168e6e1d..908626d1a3b90829b2d1fc516b6484b4c03b801e 100644
--- a/core/tests/test_tutor_api_endpoints.py
+++ b/core/tests/test_tutor_api_endpoints.py
@@ -10,7 +10,7 @@ from rest_framework.reverse import reverse
 from rest_framework.test import (APIClient, APIRequestFactory, APITestCase,
                                  force_authenticate)
 
-from core.models import Feedback, Tutor
+from core.models import Feedback
 from core.views import TutorApiViewSet
 from util.factories import GradyUserFactory
 
@@ -31,16 +31,16 @@ class TutorDeleteTest(APITestCase):
                                                    args=['UFO']))
         self.view = TutorApiViewSet.as_view({'delete': 'destroy'})
 
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         self.response = self.view(self.request, username='UFO')
 
     def test_can_delete_tutor_soapbox(self):
         """ see if the tutor was deleted """
-        self.assertEqual(0, Tutor.objects.count())
+        self.assertEqual(0, get_user_model().get_tutors().count())
 
     def test_user_is_deleted_too(self):
         """ see if the associated user was deleted (reviewer remains) """
-        self.assertEqual(1, get_user_model().objects.count())
+        self.assertNotIn(self.tutor, get_user_model().objects.all())
 
 
 class TutorListTests(APITestCase):
@@ -57,7 +57,7 @@ class TutorListTests(APITestCase):
         self.request = self.factory.get(reverse('tutor-list'))
         self.view = TutorApiViewSet.as_view({'get': 'list'})
 
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         self.response = self.view(self.request)
 
     def test_can_access(self):
@@ -68,7 +68,7 @@ class TutorListTests(APITestCase):
 
     def test_feedback_count_matches_database(self):
         def verify_fields(tutor_obj):
-            t = Tutor.objects.get(user__username=tutor_obj['username'])
+            t = get_user_model().objects.get(username=tutor_obj['username'])
             return t.get_feedback_count() == tutor_obj['feedback_count']
 
         self.assertTrue(all(map(verify_fields, self.response.data)))
@@ -81,7 +81,7 @@ class TutorListTests(APITestCase):
 
 class TutorCreateTests(APITestCase):
 
-    USERNAME = 'some weird name!'
+    USERNAME = 'some_weird_name'
 
     @classmethod
     def setUpTestData(cls):
@@ -94,14 +94,15 @@ class TutorCreateTests(APITestCase):
                                          {'username': self.USERNAME})
         self.view = TutorApiViewSet.as_view({'post': 'create'})
 
-        force_authenticate(self.request, user=self.reviewer.user)
+        force_authenticate(self.request, user=self.reviewer)
         self.response = self.view(self.request, username=self.USERNAME)
 
     def test_can_access(self):
         self.assertEqual(self.response.status_code, status.HTTP_201_CREATED)
 
     def test_can_create(self):
-        self.assertEqual(Tutor.objects.first().user.username, self.USERNAME)
+        self.assertEqual(self.USERNAME,
+                         get_user_model().get_tutors().first().username)
 
 
 class TutorDetailViewTests(APITestCase):
@@ -115,7 +116,7 @@ class TutorDetailViewTests(APITestCase):
         self.tutor = self.user_factory.make_tutor(username='fetterotto')
         self.reviewer = self.user_factory.make_reviewer()
         self.client = APIClient()
-        self.client.force_authenticate(user=self.reviewer.user)
+        self.client.force_authenticate(user=self.reviewer)
 
         url = reverse('tutor-detail', kwargs={'username': 'fetterotto'})
         self.response = self.client.get(url, format='json')
@@ -125,4 +126,4 @@ class TutorDetailViewTests(APITestCase):
 
     def test_can_view_tutor(self):
         self.assertEqual(self.response.data['username'],
-                         self.tutor.user.username)
+                         self.tutor.username)
diff --git a/core/urls.py b/core/urls.py
index 7898cedd9b7861057e317afdc17a9fe90ad1f406..3fc44639b30b2cc987ee6d0ee5af4977dce12982 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -6,11 +6,12 @@ from core import views
 
 # Create a router and register our viewsets with it.
 router = DefaultRouter()
-router.register('student', views.StudentReviewerApiViewSet)
+router.register('student', views.StudentReviewerApiViewSet,
+                base_name='student')
 router.register('examtype', views.ExamApiViewSet)
 router.register('feedback', views.FeedbackApiView)
 router.register('submissiontype', views.SubmissionTypeApiView)
-router.register('tutor', views.TutorApiViewSet)
+router.register('tutor', views.TutorApiViewSet, base_name='tutor')
 router.register('subscription', views.SubscriptionApiViewSet)
 router.register('assignment', views.AssignmentApiViewSet)
 
diff --git a/core/views.py b/core/views.py
index 140ef2e0ecafe08d07a9b190f1347146a2efc044..fc584ded203c172bdbe76fd3cc84404e723f276d 100644
--- a/core/views.py
+++ b/core/views.py
@@ -7,14 +7,16 @@ from rest_framework.decorators import api_view, detail_route
 from rest_framework.response import Response
 
 from core import models
-from core.models import (ExamType, Feedback, GeneralTaskSubscription, Student,
-                         SubmissionType, Tutor, TutorSubmissionAssignment)
+from core.models import (ExamType, GeneralTaskSubscription, StudentInfo,
+                         SubmissionType, TutorSubmissionAssignment,
+                         Feedback)
 from core.permissions import IsReviewer, IsStudent, IsTutorOrReviewer
-from core.serializers import (AssignmentDetailSerializer, AssignmentSerializer,
-                              ExamSerializer, FeedbackSerializer,
-                              StudentSerializer, StudentSerializerForListView,
+from core.serializers import (AssignmentSerializer, ExamSerializer,
+                              StudentInfoSerializer,
+                              StudentInfoSerializerForListView,
                               SubmissionTypeSerializer, SubscriptionSerializer,
-                              TutorSerializer)
+                              TutorSerializer, FeedbackSerializer,
+                              AssignmentDetailSerializer)
 
 
 @api_view()
@@ -24,16 +26,15 @@ def get_jwt_expiration_delta(request):
 
 @api_view()
 def get_user_role(request):
-    return Response({'role':
-                     type(request.user.get_associated_user()).__name__})
+    return Response({'role': request.user.role})
 
 
 class StudentSelfApiView(generics.RetrieveAPIView):
     """ Gets all data that belongs to one student """
     permission_classes = (IsStudent,)
-    serializer_class = StudentSerializer
+    serializer_class = StudentInfoSerializer
 
-    def get_object(self) -> Student:
+    def get_object(self) -> StudentInfo:
         """ The object in question is the student associated with the requests
         user. Since the permission IsStudent is satisfied the member exists """
         return self.request.user.student
@@ -65,21 +66,17 @@ class TutorApiViewSet(
         viewsets.GenericViewSet):
     """ Api endpoint for creating, listing, viewing or deleteing tutors """
     permission_classes = (IsReviewer,)
-    queryset = Tutor.objects.all()
+    queryset = models.UserAccount.objects.filter(role='Tutor')
     serializer_class = TutorSerializer
-    lookup_field = 'user__username'
+    lookup_field = 'username'
     lookup_url_kwarg = 'username'
 
-    def perform_destroy(self, instance):
-        """ deletes the tutors account and model (on delete cascade) """
-        instance.user.delete()
-
 
 class StudentReviewerApiViewSet(viewsets.ReadOnlyModelViewSet):
     """ Gets a list of all students without individual submissions """
     permission_classes = (IsReviewer,)
-    queryset = Student.objects.all()
-    serializer_class = StudentSerializerForListView
+    queryset = StudentInfo.objects.all()
+    serializer_class = StudentInfoSerializerForListView
 
 
 class SubmissionTypeApiView(viewsets.ReadOnlyModelViewSet):
diff --git a/delbert.py b/delbert.py
index d3526487ca037b4a1d0fc1c89116c25e768bc6cf..0d29750fd1d2510f8d71570d7d2474be02d04e59 100755
--- a/delbert.py
+++ b/delbert.py
@@ -11,7 +11,7 @@ django.setup()
 from django.contrib.auth.models import User
 
 import util.importer
-from core.models import Student, Submission
+from core.models import StudentInfo, Submission
 
 
 unused_variable = []
@@ -92,7 +92,7 @@ def handle_passwordlist(output=sys.stdout, instance="", **kwargs):
     writer = csv.writer(output)
     writer.writerow(['Name', 'Matrikel', 'Username', 'password', 'instance'])
 
-    for student in Student.objects.all():
+    for student in StudentInfo.objects.all():
         password = ''.join(secrets.choice(choose_from) for _ in range(3))
 
         student.user.set_password(password)
@@ -116,7 +116,7 @@ def handle_enableusers(switch, exclude, include, **kwargs):
 
 def handle_replaceusernames(matno2username_dict, **kwargs):
     matno2username = json.JSONDecoder().decode(matno2username_dict.read())
-    for student in Student.objects.all():
+    for student in StudentInfo.objects.all():
         if student.matrikel_no in matno2username:
             new_name = matno2username[student.matrikel_no]
             student.user.username = new_name
diff --git a/util/factories.py b/util/factories.py
index a27f20bdede0dffea2e12b956dff1afbc33d3262..463fb549a7a3d2926d1d7d28ceb07f8f94d3bb56 100644
--- a/util/factories.py
+++ b/util/factories.py
@@ -3,8 +3,8 @@ import secrets
 import string
 
 from core.models import UserAccount as User
-from core.models import (ExamType, Feedback, Reviewer, Student, Submission,
-                         SubmissionType, Tutor)
+from core.models import (ExamType, Feedback, StudentInfo, Submission,
+                         SubmissionType)
 
 STUDENTS = 'students'
 TUTORS = 'tutors'
@@ -44,22 +44,35 @@ class GradyUserFactory:
     def _get_random_name(self, prefix='', suffix='', k=4):
         return ''.join((prefix, self.make_password(k), suffix))
 
-    def _make_base_user(self, username, groupname, password=None,
+    def _get_group_for_user_role(self, role):
+        """ Returns the groupname for a role """
+        return {
+            'Student': 'students',
+            'Tutor': 'tutors',
+            'Reviewer': 'reviewers'
+        }[role]
+
+    def _make_base_user(self, username, role, password=None,
                         store_pw=False, **kwargs):
         """ This is a specific wrapper for the django update_or_create method of
         objects.
-            * A new user is created and password and group are set accordingly
-            * If the user was there before password is NOT change but group is.
-            * A user must only have one group.
+            * If now username is passed, a generic one will be generated
+            * A new user is created and password and role are set accordingly
+            * If the user was there before password IS changed
+            * A user must only have one role.
 
         Returns:
-            (User object, str): The user object that was added to the group and
+            (User object, str): The user object that was added to the role and
             the password of that user if it was created.
         """
+        if not username:
+            username = self._get_random_name(prefix=role.lower() + '_')
+
         username = username.strip()
 
         user, created = User.objects.update_or_create(
             username=username,
+            role=role,
             defaults=kwargs)
 
         if created:
@@ -68,51 +81,33 @@ class GradyUserFactory:
             user.save()
 
         if created and store_pw:
-            self.password_storge(username, groupname, password)
+            self.password_storge(
+                username,
+                self._get_group_for_user_role(role),
+                password)
 
         return user
 
-    def _get_user_model_for_group(self, groupname):
-        """ Returns the model class for a usergroup """
-        return {
-            STUDENTS: Student,
-            TUTORS: Tutor,
-            REVIEWERS: Reviewer,
-        }[groupname]
-
-    def _make_user_generic(self, username, groupname, **kwargs):
-        """ Provides a model with a associated user but without any defaults
-        """
-
-        if not username:
-            username = self._get_random_name(prefix=groupname.lower() + '_')
-
-        model = self._get_user_model_for_group(groupname)
-        user = self._make_base_user(username, groupname, **kwargs)
-
-        generic_user, _ = model.objects.get_or_create(user=user)
-
-        return generic_user
-
     def make_student(self, username=None, matrikel_no=None,
                      exam=None, **kwargs):
         """ Creates a student. Defaults can be passed via kwargs like in
         relation managers objects.update method. """
-        user = self._make_user_generic(username, STUDENTS, **kwargs)
+        user = self._make_base_user(username, 'Student', **kwargs)
+        studentInfo = StudentInfo.objects.get_or_create(user=user)[0]
         if matrikel_no:
-            user.matrikel_no = matrikel_no
+            studentInfo.matrikel_no = matrikel_no
         if exam:
-            user.exam = exam
-        user.save()
+            studentInfo.exam = exam
+        studentInfo.save()
         return user
 
     def make_tutor(self, username=None, **kwargs):
         """ Creates or updates a tutor if needed with defaults """
-        return self._make_user_generic(username, TUTORS, **kwargs)
+        return self._make_base_user(username, 'Tutor', **kwargs)
 
     def make_reviewer(self, username=None, **kwargs):
         """ Creates or updates a reviewer if needed with defaults """
-        return self._make_user_generic(username, REVIEWERS, **kwargs)
+        return self._make_base_user(username, 'Reviewer', **kwargs)
 
 
 def make_exams(exams=[], **kwargs):
@@ -146,7 +141,7 @@ def make_reviewers(reviewers=[], **kwargs):
 
 def make_feedback(feedback, submission_object):
     feedback['of_tutor'] = User.objects.get(
-        username=feedback['of_tutor']).get_associated_user().user
+        username=feedback['of_tutor'])
     return Feedback.objects.update_or_create(
         of_submission=submission_object,
         defaults=feedback)[0]
@@ -157,7 +152,7 @@ def make_submissions(submissions=[], **kwargs):
     for submission in submissions:
         submission_type, _ = SubmissionType.objects.get_or_create(
             name=submission.get('type', 'Auto generated type'))
-        student, _ = Student.objects.get_or_create(user=User.objects.get(
+        student, _ = StudentInfo.objects.get_or_create(user=User.objects.get(
             username=submission.get('user', 'default_user')
         ))
         submission_object, _ = Submission.objects.get_or_create(
diff --git a/util/importer.py b/util/importer.py
index d6f3080403a80c7b6f08eaa4c8e9240aa38837b9..c445545ca4f7ff13d8aa68ca69446de69028fb56 100644
--- a/util/importer.py
+++ b/util/importer.py
@@ -7,7 +7,7 @@ from typing import Callable
 import util.convert
 import util.processing
 from core.models import UserAccount as User
-from core.models import (ExamType, Feedback, Student, Submission,
+from core.models import (ExamType, Feedback, StudentInfo, Submission,
                          SubmissionType, Test)
 from util.factories import REVIEWERS, STUDENTS, TUTORS, GradyUserFactory
 from util.messages import info, warn
@@ -84,7 +84,7 @@ def add_user(username, group, **kwargs):
 def add_student(username, email, submissions, **kwargs):
 
     user = add_user(username, STUDENTS, email=email)
-    student, _ = Student.objects.update_or_create(
+    student, _ = StudentInfo.objects.update_or_create(
         user=user,
         defaults={'user': user, **kwargs}
     )