diff --git a/profile/migrations/0003_auto_20171213_1737.py b/profile/migrations/0003_auto_20171213_1737.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d4de59c5312a4407eff36f2a9459bd550e2d008
--- /dev/null
+++ b/profile/migrations/0003_auto_20171213_1737.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.3 on 2017-12-13 17:37
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('profile', '0002_auto_20171129_1828'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='profile',
+            name='biography',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='cba_url',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='dorftv_url',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='facebook_url',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='googleplus_url',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='height',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='image',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='linkedin_url',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='ppoi',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='twitter_url',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='website',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='width',
+        ),
+        migrations.RemoveField(
+            model_name='profile',
+            name='youtube_url',
+        ),
+    ]
diff --git a/profile/models.py b/profile/models.py
index bcb5ebd4b4c84f52fe8b1706c8d808d7c7b749be..0a2d867c596bd1e2d02d25a810879b6413e416bb 100644
--- a/profile/models.py
+++ b/profile/models.py
@@ -12,21 +12,8 @@ from tinymce import models as tinymce_models
 
 class Profile(models.Model):
     user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile', editable=False)
-    biography = tinymce_models.HTMLField(_("Biography"), blank=True, null=True, help_text=_("Describe yourself and your fields of interest in a few sentences."))
-    website = models.URLField(_("Website"), blank=True, help_text=_("URL to your personal website."))
-    googleplus_url = models.URLField(_("Google+ URL"), blank=True, help_text=_("URL to your Google+ profile."))
-    facebook_url = models.URLField(_("Facebook URL"), blank=True, help_text=_("URL to your Facebook profile."))
-    twitter_url = models.URLField(_("Twitter URL"), blank=True, help_text=_("URL to your Twitter profile."))
-    linkedin_url = models.URLField(_("LinkedIn URL"), blank=True, help_text=_("URL to your LinkedIn profile."))
-    youtube_url = models.URLField(_("Youtube URL"), blank=True, help_text=_("URL to your Youtube channel."))
-    dorftv_url = models.URLField(_("DorfTV URL"), blank=True, help_text=_("URL to your dorfTV channel."))
-    cba_url = models.URLField(_("CBA URL"), blank=True, help_text=_("URL to your CBA profile."))
     cba_username = models.CharField(_("CBA Username"), blank=True, max_length=60, help_text=_("Your username in CBA. This is necessary for uploading files to your account."))
     cba_user_token = models.CharField(_("CBA Token"), blank=True, max_length=255, help_text=_("The CBA upload token for your account. This is NOT your password which you use to log into CBA!"))
-    ppoi = PPOIField('Image PPOI')
-    height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
-    width = models.PositiveIntegerField('Image Width', blank=True, null=True,editable=False)
-    image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='user_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
 
     def __str__(self):
         return self.user.username
@@ -35,9 +22,4 @@ class Profile(models.Model):
         db_table = 'profile'
 
     def save(self, *args, **kwargs):
-        super(Profile, self).save(*args, **kwargs)
-
-        # Generate thumbnails
-        if self.image.name and settings.THUMBNAIL_SIZES:
-            for size in settings.THUMBNAIL_SIZES:
-                thumbnail = self.image.crop[size].name
\ No newline at end of file
+        super(Profile, self).save(*args, **kwargs)
\ No newline at end of file
diff --git a/profile/serializers.py b/profile/serializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..6cee555320d7d1aae076b0a7d4f989f6623a37d9
--- /dev/null
+++ b/profile/serializers.py
@@ -0,0 +1,8 @@
+from django.contrib.auth.models import User
+from rest_framework import serializers
+from profile.models import Profile
+
+class ProfileSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Profile
+        fields = '__all__'
\ No newline at end of file
diff --git a/profile/urls.py b/profile/urls.py
index 7ac3efa351fc14074722a1b54094f59a3b786351..ef961e396751416108478255257a693492979967 100644
--- a/profile/urls.py
+++ b/profile/urls.py
@@ -1,5 +1,9 @@
 from django.contrib import admin
+from rest_framework import routers
 
 admin.autodiscover()
 
-urlpatterns = []
\ No newline at end of file
+urlpatterns = []
+
+router = routers.DefaultRouter()
+router.register(r'users', APIUserViewSet)
\ No newline at end of file
diff --git a/program/admin.py b/program/admin.py
index c3760334ea5f58169f150f7acdd2578cd62165a7..9d4bff8fa9be27543053b0d8f8e00980f1b9f980 100644
--- a/program/admin.py
+++ b/program/admin.py
@@ -81,7 +81,7 @@ class RTRCategoryAdmin(admin.ModelAdmin):
 
 
 class HostAdmin(admin.ModelAdmin):
-    list_display = ('name',)
+    list_display = ('name','email',)
     list_filter = (ActiveHostsFilter, 'is_always_visible',)
 
 
diff --git a/program/migrations/0016_auto_20171213_1737.py b/program/migrations/0016_auto_20171213_1737.py
new file mode 100644
index 0000000000000000000000000000000000000000..c87b746ced70f2a609271de34e125fd891ebd6d5
--- /dev/null
+++ b/program/migrations/0016_auto_20171213_1737.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.3 on 2017-12-13 17:37
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import tinymce.models
+import versatileimagefield.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('program', '0015_note_audio_url'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='host',
+            name='biography',
+            field=tinymce.models.HTMLField(blank=True, help_text='Describe yourself and your fields of interest in a few sentences.', null=True, verbose_name='Biography'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='cba_url',
+            field=models.URLField(blank=True, help_text='URL to your CBA profile.', verbose_name='CBA URL'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='dorftv_url',
+            field=models.URLField(blank=True, help_text='URL to your dorfTV channel.', verbose_name='DorfTV URL'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='facebook_url',
+            field=models.URLField(blank=True, help_text='URL to your Facebook profile.', verbose_name='Facebook URL'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='googleplus_url',
+            field=models.URLField(blank=True, help_text='URL to your Google+ profile.', verbose_name='Google+ URL'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='height',
+            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='image',
+            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='user_images', verbose_name='Profile picture', width_field='width'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='linkedin_url',
+            field=models.URLField(blank=True, help_text='URL to your LinkedIn profile.', verbose_name='LinkedIn URL'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='ppoi',
+            field=versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='twitter_url',
+            field=models.URLField(blank=True, help_text='URL to your Twitter profile.', verbose_name='Twitter URL'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='width',
+            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width'),
+        ),
+        migrations.AddField(
+            model_name='host',
+            name='youtube_url',
+            field=models.URLField(blank=True, help_text='URL to your Youtube channel.', verbose_name='Youtube URL'),
+        ),
+        migrations.AlterField(
+            model_name='host',
+            name='website',
+            field=models.URLField(blank=True, help_text='URL to your personal website.', verbose_name='Website'),
+        ),
+        migrations.AlterField(
+            model_name='timeslot',
+            name='is_repetition',
+            field=models.BooleanField(default=False, verbose_name='REP'),
+        ),
+    ]
diff --git a/program/models.py b/program/models.py
index bcf6d4b2e3fde7c38c57344be2d022bad5cccd00..570169a57b86308e5e5dded59c44643fdc2a584c 100644
--- a/program/models.py
+++ b/program/models.py
@@ -243,7 +243,19 @@ class Host(models.Model):
     name = models.CharField(_("Name"), max_length=128)
     is_always_visible = models.BooleanField(_("Is always visible"), default=False)
     email = models.EmailField(_("E-Mail"), blank=True)
-    website = models.URLField(_("Website"), blank=True)
+    website = models.URLField(_("Website"), blank=True, help_text=_("URL to your personal website."))
+    biography = tinymce_models.HTMLField(_("Biography"), blank=True, null=True, help_text=_("Describe yourself and your fields of interest in a few sentences."))
+    googleplus_url = models.URLField(_("Google+ URL"), blank=True, help_text=_("URL to your Google+ profile."))
+    facebook_url = models.URLField(_("Facebook URL"), blank=True, help_text=_("URL to your Facebook profile."))
+    twitter_url = models.URLField(_("Twitter URL"), blank=True, help_text=_("URL to your Twitter profile."))
+    linkedin_url = models.URLField(_("LinkedIn URL"), blank=True, help_text=_("URL to your LinkedIn profile."))
+    youtube_url = models.URLField(_("Youtube URL"), blank=True, help_text=_("URL to your Youtube channel."))
+    dorftv_url = models.URLField(_("DorfTV URL"), blank=True, help_text=_("URL to your dorfTV channel."))
+    cba_url = models.URLField(_("CBA URL"), blank=True, help_text=_("URL to your CBA profile."))
+    ppoi = PPOIField('Image PPOI')
+    height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
+    width = models.PositiveIntegerField('Image Width', blank=True, null=True,editable=False)
+    image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='user_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
 
     class Meta:
         ordering = ('name',)
@@ -259,6 +271,14 @@ class Host(models.Model):
     def active_shows(self):
         return self.shows.filter(schedules__until__gt=datetime.today())
 
+    def save(self, *args, **kwargs):
+        super(Host, self).save(*args, **kwargs)
+
+        # Generate thumbnails
+        if self.image.name and settings.THUMBNAIL_SIZES:
+            for size in settings.THUMBNAIL_SIZES:
+                thumbnail = self.image.crop[size].name
+
 
 class Show(models.Model):
     predecessor = models.ForeignKey('self', blank=True, null=True, related_name='successors', verbose_name=_("Predecessor"))
@@ -567,7 +587,7 @@ class TimeSlot(models.Model):
     end = models.DateTimeField(_("End time"))
     show = models.ForeignKey(Show, editable=False, related_name='timeslots')
     memo = models.TextField(_("Memo"), blank=True)
-    is_repetition = models.BooleanField(_("WH"), default=False)
+    is_repetition = models.BooleanField(_("REP"), default=False)
     playlist_id = models.IntegerField(_("Playlist ID"), null=True)
 
     objects = TimeSlotManager()
@@ -580,7 +600,7 @@ class TimeSlot(models.Model):
     def __str__(self):
         start = self.start.strftime('%a, %d.%m.%Y %H:%M')
         end = self.end.strftime('%H:%M')
-        is_repetition = ' ' + _('WH') if self.schedule.is_repetition is 1 else ''
+        is_repetition = ' ' + _('REP') if self.schedule.is_repetition is 1 else ''
 
         return '%s - %s  %s (%s)' % (start, end, is_repetition, self.show.name)
 
diff --git a/program/serializers.py b/program/serializers.py
index 2850bb3961d782df84b0cc6eca31e0a6449a4e79..47594149f97eea514fc6da87c9c1e592663ac6d8 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -4,12 +4,7 @@ from rest_framework import serializers, status
 from rest_framework.response import Response
 from program.models import Show, Schedule, TimeSlot, Category, RTRCategory, Host, Language, Topic, MusicFocus, Note, Type, Language
 from profile.models import Profile
-
-
-class ProfileSerializer(serializers.ModelSerializer):
-    class Meta:
-        model = Profile
-        fields = '__all__'
+from profile.serializers import ProfileSerializer
 
 
 class UserSerializer(serializers.ModelSerializer):
@@ -31,16 +26,8 @@ class UserSerializer(serializers.ModelSerializer):
         instance.last_name = validated_data.get('last_name', instance.last_name)
         instance.email = validated_data.get('email', instance.email)
 
+        # TODO: How to hook into this from ProfileSerializer without having to call it here?
         profile = Profile.objects.get(user=instance.id)
-        profile.biography = validated_data['profile'].get('biography')
-        profile.website = validated_data['profile'].get('website')
-        profile.googleplus_url = validated_data['profile'].get('googleplus_url')
-        profile.facebook_url = validated_data['profile'].get('facebook_url')
-        profile.twitter_url = validated_data['profile'].get('twitter_url')
-        profile.linkedin_url = validated_data['profile'].get('linkedin_url')
-        profile.youtube_url = validated_data['profile'].get('youtube_url')
-        profile.dorftv_url = validated_data['profile'].get('dorftv_url')
-        profile.cba_url = validated_data['profile'].get('cba_url')
         profile.cba_username = validated_data['profile'].get('cba_username')
         profile.cba_user_token = validated_data['profile'].get('cba_user_token')
         profile.save()
@@ -60,6 +47,27 @@ class HostSerializer(serializers.ModelSerializer):
         model = Host
         fields = '__all__'
 
+    def update(self, instance, validated_data):
+        """
+        Update and return an existing Host instance, given the validated data.
+        """
+        instance.name = validated_data.get('name', instance.name)
+        instance.is_always_visible = validated_data.get('is_always_visible', instance.is_always_visible)
+        instance.email = validated_data.get('email', instance.email)
+        instance.website = validated_data.get('website', instance.website)
+        instance.biography = validated_data.get('biography', instance.biography)
+        instance.googleplus_url = validated_data.get('googleplus_url', instance.googleplus_url)
+        instance.facebook_url = validated_data.get('facebook_url', instance.facebook_url)
+        instance.twitter_url = validated_data.get('twitter_url', instance.twitter_url)
+        instance.linkedin_url = validated_data.get('linkedin_url', instance.linkedin_url)
+        instance.youtube_url = validated_data.get('youtube_url', instance.youtube_url)
+        instance.dorftv_url = validated_data.get('dorftv_url', instance.dorftv_url)
+        instance.cba_url = validated_data.get('cba_url', instance.cba_url)
+        instance.image = validated_data.get('image', instance.image)
+
+        instance.save()
+        return instance
+
 
 class LanguageSerializer(serializers.ModelSerializer):
     class Meta:
diff --git a/program/views.py b/program/views.py
index bdd3534b30a577ce4c790c35f4ad843e60fa5c69..85f468dc0581cccf9f4401cff4221a862ca264e5 100644
--- a/program/views.py
+++ b/program/views.py
@@ -18,7 +18,6 @@ from rest_framework.response import Response
 from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope
 
 from program.models import Type, MusicFocus, Language, Note, Show, Category, RTRCategory, Topic, TimeSlot, Host, Schedule
-from profile.models import Profile
 from program.serializers import TypeSerializer, LanguageSerializer, MusicFocusSerializer, NoteSerializer, ShowSerializer, CategorySerializer, RTRCategorySerializer, TopicSerializer, TimeSlotSerializer, HostSerializer, UserSerializer
 from program.utils import tofirstdayinisoweek, get_cached_shows