diff --git a/aleksis/core/admin.py b/aleksis/core/admin.py
index bdcda1e35e4bbd427e35e32b414e6931cba00ae6..e3258ed33bea0fc4dbcb452c2f2f57573212dbe2 100644
--- a/aleksis/core/admin.py
+++ b/aleksis/core/admin.py
@@ -1,6 +1,15 @@
 from django.contrib import admin
 
-from .models import Group, Person, School, SchoolTerm, Activity, Notification, Announcement
+from .models import (
+    Group,
+    Person,
+    School,
+    SchoolTerm,
+    Activity,
+    Notification,
+    Announcement,
+    AnnouncementRecipient,
+)
 
 admin.site.register(Person)
 admin.site.register(Group)
@@ -8,4 +17,16 @@ admin.site.register(School)
 admin.site.register(SchoolTerm)
 admin.site.register(Activity)
 admin.site.register(Notification)
-admin.site.register(Announcement)
+
+
+class AnnouncementRecipientInline(admin.StackedInline):
+    model = AnnouncementRecipient
+
+
+class AnnouncementAdmin(admin.ModelAdmin):
+    inlines = [
+        AnnouncementRecipientInline,
+    ]
+
+
+admin.site.register(Announcement, AnnouncementAdmin)
diff --git a/aleksis/core/migrations/0013_multiple_recipients_announcement.py b/aleksis/core/migrations/0013_multiple_recipients_announcement.py
new file mode 100644
index 0000000000000000000000000000000000000000..76574ecd1210f16c1b265eab61f582184faca310
--- /dev/null
+++ b/aleksis/core/migrations/0013_multiple_recipients_announcement.py
@@ -0,0 +1,51 @@
+# Generated by Django 3.0.3 on 2020-02-19 18:14
+
+import aleksis.core.models
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contenttypes', '0002_remove_content_type_name'),
+        ('core', '0012_announcement'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='announcement',
+            options={'verbose_name': 'Announcement', 'verbose_name_plural': 'Announcements'},
+        ),
+        migrations.RemoveField(
+            model_name='announcement',
+            name='content_type',
+        ),
+        migrations.RemoveField(
+            model_name='announcement',
+            name='recipient_id',
+        ),
+        migrations.AlterField(
+            model_name='announcement',
+            name='description',
+            field=models.TextField(blank=True, max_length=500, verbose_name='Description'),
+        ),
+        migrations.AlterField(
+            model_name='announcement',
+            name='valid_until',
+            field=models.DateTimeField(default=aleksis.core.models.now_plus_one_day, verbose_name='Date and time until when to show'),
+        ),
+        migrations.CreateModel(
+            name='AnnouncementRecipient',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('recipient_id', models.PositiveIntegerField()),
+                ('announcement', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recipients', to='core.Announcement')),
+                ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
+            ],
+        ),
+        migrations.AlterModelOptions(
+            name='announcementrecipient',
+            options={'verbose_name': 'Announcement recipient', 'verbose_name_plural': 'Announcement recipients'},
+        ),
+    ]
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index e1dae558196ec24093496f7ccdd588bdcdcbca43..bcc445fa8ab7da58e2c44a1d42a33de85651e6a5 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -230,7 +230,7 @@ class Group(ExtensibleModel):
 
     @property
     def announcement_recipients(self):
-        return list(self.members) + list(self.owners)
+        return list(self.members.all()) + list(self.owners.all())
 
     def __str__(self) -> str:
         return "%s (%s)" % (self.name, self.short_name)
@@ -280,6 +280,10 @@ class Notification(models.Model):
         verbose_name_plural = _("Notifications")
 
 
+def now_plus_one_day():
+    return timezone.datetime.now() + timedelta(days=1)
+
+
 class Announcement(models.Model):
     title = models.CharField(max_length=150, verbose_name=_("Title"))
     description = models.TextField(max_length=500, verbose_name=_("Description"), blank=True)
@@ -290,13 +294,9 @@ class Announcement(models.Model):
     )
     valid_until = models.DateTimeField(
         verbose_name=_("Date and time until when to show"),
-        default=lambda: timezone.datetime.now() + timedelta(days=1),
+        default=now_plus_one_day,
     )
 
-    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
-    recipient_id = models.PositiveIntegerField()
-    recipient = GenericForeignKey("content_type", "recipient_id")
-
     @classmethod
     def relevant_for(cls, obj: Union[models.Model, models.QuerySet]) -> models.QuerySet:
         """ Get a QuerySet with all announcements relevant for a certain Model (e.g. a Group)
@@ -310,7 +310,7 @@ class Announcement(models.Model):
             ct = ContentType.objects.get_for_model(obj)
             pks = [obj.pk]
 
-        return cls.objects.filter(content_type=ct, recipient_id__in=pks)
+        return cls.objects.filter(recipients__content_type=ct, recipients__recipient_id__in=pks)
 
     @classmethod
     def for_person_at_time(cls, person: Person, when: Optional[datetime] = None) -> List:
@@ -329,10 +329,34 @@ class Announcement(models.Model):
         return announcements_for_person
 
     @property
-    def recipient_persons(self) -> Union[models.QuerySet, Sequence[models.Model]]:
-        """ Return a list of Persons this announcement is relevant for
+    def recipient_persons(self) -> Sequence[Person]:
+        """ Return a list of Persons this announcement is relevant for """
+
+        persons = []
+        for recipient in self.recipients.all():
+            persons += recipient.persons
+        return persons
 
-        If the recipient is a Person, return that object. If not, it returns the QUerySet
+    def __str__(self):
+        return self.title
+
+    class Meta:
+        verbose_name = _("Announcement")
+        verbose_name_plural = _("Announcements")
+
+
+class AnnouncementRecipient(models.Model):
+    announcement = models.ForeignKey(Announcement, on_delete=models.CASCADE, related_name="recipients")
+
+    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
+    recipient_id = models.PositiveIntegerField()
+    recipient = GenericForeignKey("content_type", "recipient_id")
+
+    @property
+    def persons(self) -> Sequence[Person]:
+        """ Return a list of Persons selected by this recipient object
+
+        If the recipient is a Person, return that object. If not, it returns the list
         from the announcement_recipients field on the target model.
         """
 
@@ -342,11 +366,11 @@ class Announcement(models.Model):
             return getattr(self.recipient, "announcement_recipients", [])
 
     def __str__(self):
-        return self.title
+        return str(self.recipient)
 
     class Meta:
-        verbose_name = _("Announcement")
-        verbose_name_plural = _("Announcements")
+        verbose_name = _("Announcement recipient")
+        verbose_name_plural = _("Announcement recipients")
 
 
 class DashboardWidget(PolymorphicModel):