diff --git a/backend/delbert.py b/backend/delbert.py
index 557260f5c0a257d7d76e6fbfca6304aae899b10c..eb65722209d34956c5c0696d610480b2f778da60 100644
--- a/backend/delbert.py
+++ b/backend/delbert.py
@@ -2,18 +2,19 @@ import argparse
 import csv
 import json
 import os
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'grady.settings')
 import secrets
 import sys
 
 import django
+django.setup()
 from django.contrib.auth.models import User
 
 import util.importer
 from core.models import Student, Submission
 
-os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'grady.settings')
 
-django.setup()
+
 
 
 def parseme():
diff --git a/backend/util/factories.py b/backend/util/factories.py
index 953d323d6d306209c953123347fdc8ed3c119e3b..fe14c5e5949c682a4d7c6488393c001e9b6a2e75 100644
--- a/backend/util/factories.py
+++ b/backend/util/factories.py
@@ -2,13 +2,44 @@ import configparser
 import secrets
 
 from core.models import UserAccount as User, Student, Tutor, Reviewer
-from util.importer import PASSWORDS
+
+STUDENTS = 'students'
+TUTORS = 'tutors'
+REVIEWERS = 'reviewers'
+
+PASSWORDS = '.importer_passwords'
+
+def get_xkcd_password(k=2):
+    with open('/usr/share/dict/words') as words:
+        choose_from = list({word.strip().lower()
+                            for word in words if 5 < len(word) < 8})
+
+    return ''.join(secrets.choice(choose_from) for _ in range(k))
+
+
+def store_password(username, groupname, password):
+    storage = configparser.ConfigParser()
+    storage.read(PASSWORDS)
+
+    if not groupname in storage:
+        storage[groupname] = {}
+
+    storage[groupname][username] = password
+
+    with open(PASSWORDS, 'w') as passwd_file:
+        storage.write(passwd_file)
+
+
 
 
 class GradyUserFactory:
 
-    def __init__(self, password_generator_func=get_xkcd_password, *args, **kwargs):
+    def __init__(self,
+                password_generator_func=get_xkcd_password,
+                password_storge=store_password
+                *args, **kwargs):
         self.password_generator_func = password_generator_func
+        self.password_storge = password_storge
 
     @staticmethod
     def _get_random_name(prefix='', suffix='', k=1):
@@ -37,7 +68,7 @@ class GradyUserFactory:
             user.save()
 
         if created and store_pw:
-            store_password(username, groupname, password)
+            self.password_storge(username, groupname, password)
 
         return user
 
@@ -80,31 +111,3 @@ class GradyUserFactory:
     def make_reviewer(self, username=None, **kwargs):
         """ Creates or updates a reviewer if needed with defaults """
         return self._make_user_generic(username, REVIEWERS, **kwargs)
-
-
-STUDENTS = 'students'
-TUTORS = 'tutors'
-REVIEWERS = 'reviewers'
-
-
-def get_xkcd_password(k=2):
-    with open('/usr/share/dict/words') as words:
-        choose_from = list({word.strip().lower()
-                            for word in words if 5 < len(word) < 8})
-
-    return ''.join(secrets.choice(choose_from) for _ in range(k))
-
-
-def store_password(username, groupname, password):
-    storage = configparser.ConfigParser()
-    storage.read(PASSWORDS)
-
-    if not groupname in storage:
-        storage[groupname] = {}
-
-    storage[groupname][username] = password
-
-    with open(PASSWORDS, 'w') as passwd_file:
-        storage.write(passwd_file)
-
-
diff --git a/backend/util/importer.py b/backend/util/importer.py
index 0c77ba2f7123d602201d688c4ca5384f21453ec4..299f4ae547c1b8e1a8a9dcd2568bf3ca29d0b407 100644
--- a/backend/util/importer.py
+++ b/backend/util/importer.py
@@ -1,18 +1,23 @@
+import configparser
 import csv
 import json
 import os
 import readline
+import secrets
 from typing import Callable
 
 import util.convert
 import util.processing
-from core.models import (ExamType, Feedback, Student, Submission,
-                         SubmissionType, Test)
 from core.models import UserAccount as User
-from util.factories import GradyUserFactory, STUDENTS, TUTORS, REVIEWERS
+from core.models import (ExamType, Feedback, Reviewer, Student, Submission,
+                         SubmissionType, Test, Tutor)
 from util.messages import info, warn
 from util.processing import EmptyTest
 
+STUDENTS = 'students'
+TUTORS = 'tutors'
+REVIEWERS = 'reviewers'
+
 HISTFILE = '.importer_history'
 RECORDS = '.importer'
 PASSWORDS = '.importer_passwords'
@@ -57,6 +62,14 @@ class chdir_context(object):
         os.chdir(self.old_dir)
 
 
+def get_xkcd_password(k=2):
+    with open('/usr/share/dict/words') as words:
+        choose_from = list({word.strip().lower()
+                            for word in words if 5 < len(word) < 8})
+
+    return ''.join(secrets.choice(choose_from) for _ in range(k))
+
+
 def i(prompt: str, default: str='', is_path: bool=False, is_file: bool=False):
     if default is YES or default is NO:
         answer = valid[input(f'[Q] {prompt} ({default}): ').lower() or ('y' if YES == default else 'n')]
@@ -72,8 +85,96 @@ def i(prompt: str, default: str='', is_path: bool=False, is_file: bool=False):
     return answer
 
 
-# TODO more factories
+def store_password(username, groupname, password):
+    storage = configparser.ConfigParser()
+    storage.read(PASSWORDS)
+
+    if not groupname in storage:
+        storage[groupname] = {}
+
+    storage[groupname][username] = password
+
+    with open(PASSWORDS, 'w') as passwd_file:
+        storage.write(passwd_file)
+
+
+class GradyUserFactory:
+
+    def __init__(self, password_generator_func=get_xkcd_password, *args, **kwargs):
+        self.password_generator_func = password_generator_func
+
+    @staticmethod
+    def _get_random_name(prefix='', suffix='', k=1):
+        return ''.join((prefix, get_xkcd_password(k), suffix))
+
+    def _make_base_user(self, username, groupname, 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.
+
+        Returns:
+            (User object, str): The user object that was added to the group and
+            the password of that user if it was created.
+        """
+        username = username.strip()
 
+        user, created = User.objects.update_or_create(
+            username=username,
+            defaults=kwargs)
+
+        if created:
+            password = self.password_generator_func()
+            user.set_password(password)
+            user.save()
+
+        if created and store_pw:
+            store_password(username, groupname, 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)
+        if matrikel_no:
+            user.objects.update(matrikel_no=matrikel_no)
+        if exam:
+            user.objects.update(exam=exam)
+        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)
+
+    def make_reviewer(self, username=None, **kwargs):
+        """ Creates or updates a reviewer if needed with defaults """
+        return self._make_user_generic(username, REVIEWERS, **kwargs)
+
+# TODO more factories
 
 def add_user(username, group, **kwargs):
     user = GradyUserFactory()._make_base_user(