diff --git a/src/core/models/events.py b/src/core/models/events.py
index c95b67a066bb3ba94f3a343172566c33133d14fc..a79c519c2c14b1cd5e6f3ced0f0d62140fde457d 100644
--- a/src/core/models/events.py
+++ b/src/core/models/events.py
@@ -34,6 +34,8 @@ from .users import PlatformUser
 
 SIMPLE_TIME_RE = compile(r'(.*\s)?(\d+:\d+)$')
 
+logger = logging.getLogger(__name__)
+
 
 class EventDurationFormField(DurationField):
     def to_python(self, value):
@@ -225,10 +227,11 @@ class Event(TaggedItemMixin, BackendMixin, models.Model):
     @property
     def public_speakers(self) -> list:
         """Returns a list of all public speakers of this event."""
-        persons = self.participants.filter(is_public=True, role=EventParticipant.Role.SPEAKER).values_list('participant', flat=True)
+        persons = (
+            self.participants.filter(is_public=True, role=EventParticipant.Role.SPEAKER).select_related('participant').order_by('participant__display_name')
+        )
 
-        # If there is no speaker for an SoS, the owner is automatically added.
-        if self.kind == Event.Kind.SELF_ORGANIZED and not persons and self.owner:
+        if len(persons) == 0 and self.kind == Event.Kind.SELF_ORGANIZED and self.owner:
             persons.add(self.owner)
 
         return persons
@@ -302,16 +305,24 @@ class Event(TaggedItemMixin, BackendMixin, models.Model):
             names = OrderedSet(self.speakers)
         except AttributeError:
             names = OrderedSet()
-            names |= OrderedSet(self.participants.filter(is_public=True, role=EventParticipant.Role.SPEAKER).values_list('participant__username', flat=True))
-
-        if self.additional_data is not None:
-            for p in self.additional_data.get('persons', []):
-                name = p.get('public_name', p.get('name'))
-                if name:
-                    names.add(name)
+            names |= OrderedSet(
+                self.participants.filter(is_public=True, role=EventParticipant.Role.SPEAKER)
+                .order_by('participant__display_name')
+                .values_list('participant__display_name', flat=True)
+            )
 
-        if self.kind == Event.Kind.SELF_ORGANIZED and self.owner:
-            names.add(self.owner.username)
+        # if the "correct" participant list is empty, check if we can derive some speaker names
+        if len(names) == 0:
+            # imported events might have a "persons" list in the additional data
+            if self.additional_data is not None:
+                for p in self.additional_data.get('persons', []):
+                    name = p.get('public_name', p.get('name'))
+                    if name:
+                        names.add(name)
+
+            # for SoS, use the owner as a speaker
+            if self.kind == Event.Kind.SELF_ORGANIZED and self.owner:
+                names.add(self.owner.username)
 
         return names
 
diff --git a/src/plainui/views/events.py b/src/plainui/views/events.py
index 2c6ed8fc760095c959bf5cfaa9c8de18267520a9..0b1535e385925ebe14240a34e57923300e1e82a0 100644
--- a/src/plainui/views/events.py
+++ b/src/plainui/views/events.py
@@ -121,8 +121,8 @@ class ChannelEventsView(ConferenceRequiredMixin, TemplateView):
             .order_by('room_id', 'schedule_start')
             .distinct('room_id')
         )
-        speakers = EventParticipant.objects.filter(is_public=True, role=EventParticipant.Role.SPEAKER).order_by('participant__username')
-        speakers = speakers.annotate(speaker_name=F('participant__username'))
+        speakers = EventParticipant.objects.filter(is_public=True, role=EventParticipant.Role.SPEAKER).order_by('participant__display_name')
+        speakers = speakers.annotate(speaker_name=F('participant__display_name'))
         current_events_qs = current_events_qs.prefetch_related(Prefetch('participants', queryset=speakers, to_attr='speakers'))
 
         current_events = {}  # type: dict[UUID, Event]