diff --git a/.gitignore b/.gitignore
index bd57f96cdfe95a3b0a40bcebc52c32d440be31ed..e061740b3733c98a4c82aa903a452dd912b15dda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 *.pyc
 .idea
 *.sqlite3
+*.log
 /media
 /build
 /dist
diff --git a/management/forms.py b/management/forms.py
index 8fd739f85868384959ba86617dcdda4264ff05a6..6f22792351f3d594ed26927515affe5987d029d3 100644
--- a/management/forms.py
+++ b/management/forms.py
@@ -208,7 +208,7 @@ class AddElectionForm(forms.ModelForm, TemplateStringForm):
         model = Election
         fields = (
             'title', 'start_date', 'end_date', 'session', 'max_votes_yes', 'voters_self_apply', 'send_emails_on_start',
-            'remind_text', 'disable_abstention', 'result_unpublished')
+            'remind_text', 'enable_abstention', 'result_published')
 
         labels = {
             'title': 'Election Name',
@@ -217,10 +217,10 @@ class AddElectionForm(forms.ModelForm, TemplateStringForm):
             'voters_self_apply': 'Voters can apply for the election',
             'send_emails_on_start': 'Voters receive an e-mail when the election starts<br>'
                                     '(useful for elections that last several days)',
-            'disable_abstention': 'Disable the option to abstain in this election<br>'
-                                  '(only YES and NO votes will be allowed)',
+            'enable_abstention': 'Enable the option to abstain in this election<br>'
+                                 '(YES,  NO and ABSTENTION votes will be allowed)',
             'remind_text': '',
-            'result_unpublished': 'Disable auto publish of the election results',
+            'result_published': 'Automatically publish the election results',
         }
 
     def clean_remind_text(self):
diff --git a/management/management/commands/create_admin.py b/management/management/commands/create_admin.py
index 291ef6d6e3cc9a4f7fe29e84a816fe527934d5b7..605a8efa5a1b64cafd819fba925b7968015caf93 100644
--- a/management/management/commands/create_admin.py
+++ b/management/management/commands/create_admin.py
@@ -60,4 +60,4 @@ class Command(BaseCommand):
 
         manager.save()
         self.stdout.write(self.style.SUCCESS(
-            f'Successfully created management login with username {username}, email {email}, password: {password}'))
+            f'Successfully created management login with username: {username}, email: {email}'))
diff --git a/management/templates/management/add_election.html b/management/templates/management/add_election.html
index 17873c02ad45da25c5813fd0412eea4e2636c169..47df2a622b868889f5de3b7c03f85f1aaf4d0666 100644
--- a/management/templates/management/add_election.html
+++ b/management/templates/management/add_election.html
@@ -17,7 +17,7 @@
 
             {{ form|as_crispy_errors }}
             {% for field in form %}
-              {% if field.html_name != "remind_text" and field.html_name != "send_emails_on_start" and field.html_name != "voters_self_apply" and field.html_name != "email" and field.html_name != 'disable_abstention' and field.html_name != 'result_unpublished' %}
+              {% if field.html_name != "remind_text" and field.html_name != "send_emails_on_start" and field.html_name != "voters_self_apply" and field.html_name != "email" and field.html_name != 'enable_abstention' and field.html_name != 'result_published' %}
                 {{ field|as_crispy_field }}
               {% endif %}
             {% endfor %}
@@ -32,8 +32,8 @@
                 </span>
               </div>
               <div id="collapseOne" class="card-body collapse{% if form.remind_text.value %} show{% endif %}">
-                {{ form.result_unpublished|as_crispy_field }}
-                {{ form.disable_abstention|as_crispy_field }}
+                {{ form.result_published|as_crispy_field }}
+                {{ form.enable_abstention|as_crispy_field }}
                 {{ form.voters_self_apply|as_crispy_field }}
                 {{ form.send_emails_on_start|as_crispy_field }}
                 <h5>Remind email template text</h5>
diff --git a/management/templates/management/election.html b/management/templates/management/election.html
index aba5e8ceac651de29089543f9e8b20f05f945a47..471f5c780fd57f764e5b67544eafec2706ab3717 100644
--- a/management/templates/management/election.html
+++ b/management/templates/management/election.html
@@ -120,7 +120,7 @@
             <h4>Result</h4>
             {% include 'management/results.html' %}
 
-            {% if election.result_unpublished %}
+            {% if not election.result_published %}
               <hr>
               <form action="{% url 'management:election' election.pk %}" method="post">
                 {% csrf_token %}
diff --git a/management/views.py b/management/views.py
index d2592d611e9f6017adfa1c56c8aeb119cb9ba223..475dede475d58c9537580ccbe130ab36f2e64c9a 100644
--- a/management/views.py
+++ b/management/views.py
@@ -34,6 +34,7 @@ from management.forms import (
     SessionSettingsForm
 )
 from vote.models import Election, Application, Voter
+from vote.selectors import open_elections, upcoming_elections, published_elections, closed_elections
 
 logger = logging.getLogger('management.view')
 
@@ -90,19 +91,13 @@ def index(request):
 def session_detail(request, pk=None):
     manager = request.user
     session = manager.sessions.get(id=pk)
-    elections = session.elections.order_by('pk')
-    existing_elections = bool(elections)
-    open_elections = [e for e in elections if e.is_open]
-    upcoming_elections = [e for e in elections if not e.started]
-    published_elections = [e for e in elections if e.closed and not e.result_unpublished]
-    closed_elections = [e for e in elections if e.closed and e.result_unpublished]
     context = {
         'session': session,
-        'existing_elections': existing_elections,
-        'open_elections': open_elections,
-        'upcoming_elections': upcoming_elections,
-        'published_elections': published_elections,
-        'closed_elections': closed_elections,
+        'existing_elections': bool(session.elections),
+        'open_elections': open_elections(session),
+        'upcoming_elections': upcoming_elections(session),
+        'published_elections': published_elections(session),
+        'closed_elections': closed_elections(session),
         'voters': session.participants.all()
     }
     return render(request, template_name='management/session.html', context=context)
@@ -248,7 +243,7 @@ def election_detail(request, pk):
             context['start_election_form'] = form
 
     if request.POST and request.POST.get('action') == 'publish':
-        election.result_unpublished = False
+        election.result_published = True
         election.save()
 
     return render(request, template_name='management/election.html', context=context)
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 7d536fbc518a5b4aaded10235b82170a8613e891..34bfbce35a15d20f72f07b8d0d5533d82f39863f 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -3,3 +3,4 @@ pylint~=2.8
 pylint-django~=2.4
 django-stubs
 build
+freezegun
\ No newline at end of file
diff --git a/vote/forms.py b/vote/forms.py
index 1c3f878265bb8895c94c4ca8df69e73c176f99de..0ec5006f42fd431c34731a9af31e399796c8a45e 100644
--- a/vote/forms.py
+++ b/vote/forms.py
@@ -61,12 +61,12 @@ class VoteBoundField(forms.BoundField):
 
 
 class VoteField(forms.ChoiceField):
-    def __init__(self, *, application, disable_abstention=False, **kwargs):
+    def __init__(self, *, application, enable_abstention=True, **kwargs):
         super().__init__(
             label=application.get_display_name(),
-            choices=VOTE_CHOICES_NO_ABSTENTION if disable_abstention else VOTE_CHOICES,
+            choices=VOTE_CHOICES if enable_abstention else VOTE_CHOICES_NO_ABSTENTION,
             widget=forms.RadioSelect(),
-            initial=None if disable_abstention else VOTE_ABSTENTION,
+            initial=VOTE_ABSTENTION if enable_abstention else None,
             **kwargs
         )
         self.application = application
@@ -84,14 +84,14 @@ class VoteForm(forms.Form):
         if self.election.max_votes_yes is not None:
             self.max_votes_yes = self.election.max_votes_yes
         else:
-            self.max_votes_yes = self.election.applications.count()
+            self.max_votes_yes = self.election.applications.all().count()
 
         # dynamically construct form fields
-        for application in self.election.applications:
+        for application in self.election.applications.all():
             self.fields[f'{application.pk}'] = VoteField(application=application,
-                                                         disable_abstention=self.election.disable_abstention)
+                                                         enable_abstention=self.election.enable_abstention)
 
-        self.num_applications = len(self.election.applications)
+        self.num_applications = self.election.applications.all().count()
 
     def clean(self):
         super().clean()
diff --git a/vote/migrations/0028_auto_20210804_2335.py b/vote/migrations/0028_auto_20210804_2335.py
new file mode 100644
index 0000000000000000000000000000000000000000..5bdd978aa265c923bd3839fc0398aebdd64b5ca2
--- /dev/null
+++ b/vote/migrations/0028_auto_20210804_2335.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.1.13 on 2021-08-04 21:35
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('vote', '0027_change_field_type_results_published'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='application',
+            name='election',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='applications', to='vote.election'),
+        ),
+        migrations.AlterField(
+            model_name='application',
+            name='voter',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='applications', to='vote.voter'),
+        ),
+    ]
diff --git a/vote/migrations/0029_rename_unpublished_and_disable_abstention.py b/vote/migrations/0029_rename_unpublished_and_disable_abstention.py
new file mode 100644
index 0000000000000000000000000000000000000000..dffbda68eb954e0c5fdf6bdb33460b0f68b3bc60
--- /dev/null
+++ b/vote/migrations/0029_rename_unpublished_and_disable_abstention.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.1.13 on 2021-08-06 08:40
+
+from django.db import migrations
+from django.db.models import Q
+
+
+def update_values(apps, schema_editor):
+    election = apps.get_model('vote', 'election')
+    election.objects.update(result_published=Q(result_published=False))
+    election.objects.update(enable_abstention=Q(enable_abstention=False))
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('vote', '0028_auto_20210804_2335'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='election',
+            old_name='result_unpublished',
+            new_name='result_published',
+        ),
+        migrations.RenameField(
+            model_name='election',
+            old_name='disable_abstention',
+            new_name='enable_abstention',
+        ),
+        migrations.RunPython(update_values, reverse_code=update_values),
+    ]
diff --git a/vote/models.py b/vote/models.py
index 9730ae32f1a75f529727e35e698a4df1e703d9f3..e1e00924ee09e7f48f64e57935d0e966e7014836 100644
--- a/vote/models.py
+++ b/vote/models.py
@@ -97,8 +97,8 @@ class Election(models.Model):
     end_date = models.DateTimeField(blank=True, null=True)
     max_votes_yes = models.IntegerField(blank=True, null=True)
     session = models.ForeignKey(Session, related_name='elections', on_delete=CASCADE)
-    result_unpublished = models.BooleanField(null=False, default=True)
-    disable_abstention = models.BooleanField(default=False)
+    result_published = models.BooleanField(null=False, default=False)
+    enable_abstention = models.BooleanField(default=True)
     voters_self_apply = models.BooleanField(default=False)
     send_emails_on_start = models.BooleanField(default=False)
     remind_text = models.TextField(max_length=8000, blank=True, null=True)
@@ -107,24 +107,24 @@ class Election(models.Model):
     @property
     def started(self):
         if self.start_date is not None:
-            return timezone.now() > self.start_date
+            return timezone.now() >= self.start_date
 
         return False
 
     @property
     def closed(self):
         if self.end_date:
-            return self.end_date < timezone.now()
+            return self.end_date <= timezone.now()
 
         return False
 
     @property
     def is_open(self):
         if self.start_date and self.end_date:
-            return self.start_date < timezone.now() < self.end_date
+            return self.start_date <= timezone.now() < self.end_date
 
         if self.start_date:
-            return self.start_date < timezone.now()
+            return self.start_date <= timezone.now()
 
         return False
 
@@ -135,10 +135,6 @@ class Election(models.Model):
 
         return True
 
-    @property
-    def applications(self):
-        return Application.objects.filter(election=self)
-
     @property
     def election_summary(self):
         if not self.closed:
@@ -163,9 +159,9 @@ class Election(models.Model):
         return self.open_votes.count()
 
     def number_votes_cast(self):
-        if self.applications.count() == 0:
+        if self.applications.all().count() == 0:
             return 0
-        return int(self.votes.count() / self.applications.count())
+        return int(self.votes.count() / self.applications.all().count())
 
     def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
         super().save(force_insert, force_update, using, update_fields)
@@ -290,9 +286,12 @@ class Voter(models.Model):
     def is_active(self):
         return self.has_usable_password()
 
-    def can_vote(self, election):
+    def can_vote(self, election: Election):
         return election.is_open and OpenVote.objects.filter(voter_id=self.voter_id, election_id=election.id).exists()
 
+    def has_applied(self, election: Election):
+        return self.applications.filter(election=election).exists()
+
     @property
     def is_staff(self):
         return False
@@ -458,10 +457,10 @@ def avatar_file_name(instance, filename):
 class Application(models.Model):
     text = models.TextField(max_length=250, blank=True)
     avatar = models.ImageField(upload_to=avatar_file_name, null=True, blank=True)
-    election = models.ForeignKey(Election, related_name='application', on_delete=models.CASCADE)
+    election = models.ForeignKey(Election, related_name='applications', on_delete=models.CASCADE)
     display_name = models.CharField(max_length=256)
     email = models.EmailField(null=True, blank=True)
-    voter = models.ForeignKey(Voter, related_name="application", null=True, blank=True, on_delete=models.CASCADE)
+    voter = models.ForeignKey(Voter, related_name="applications", null=True, blank=True, on_delete=models.CASCADE)
 
     _old_avatar = None
 
diff --git a/vote/selectors.py b/vote/selectors.py
new file mode 100644
index 0000000000000000000000000000000000000000..f08a82310ea6ea672b80c2a9a40946f2d7c1a0a7
--- /dev/null
+++ b/vote/selectors.py
@@ -0,0 +1,31 @@
+from django.db.models import Q
+from django.utils import timezone
+
+from vote.models import Election, Session
+
+
+def upcoming_elections(session: Session):
+    return Election.objects.filter(session=session).filter(
+        Q(start_date__gt=timezone.now()) | Q(start_date__isnull=True)
+    ).order_by('start_date')
+
+
+def open_elections(session: Session):
+    return Election.objects.filter(session=session).filter(
+        Q(start_date__isnull=False, end_date__isnull=False, start_date__lte=timezone.now(), end_date__gt=timezone.now())
+        | Q(start_date__isnull=False, end_date__isnull=True, start_date__lte=timezone.now())
+    ).order_by('-start_date')
+
+
+def _closed_elections(session: Session):
+    return Election.objects.filter(session=session).filter(
+        Q(end_date__lte=timezone.now(), end_date__isnull=False)
+    ).order_by('-start_date')
+
+
+def published_elections(session: Session):
+    return _closed_elections(session).filter(result_published=True)
+
+
+def closed_elections(session: Session):
+    return _closed_elections(session).filter(result_published=False)
diff --git a/vote/templates/vote/index_election_item.html b/vote/templates/vote/index_election_item.html
index 6413fa3d6d54ed60209680b06d79add496f5786d..34ad03b6182688c0789dfcfe9e041002ef498fa8 100644
--- a/vote/templates/vote/index_election_item.html
+++ b/vote/templates/vote/index_election_item.html
@@ -24,7 +24,7 @@
     <div class="list-group mt-3">
       {% if can_vote %}
         <a class="btn btn-primary" role="button" href="{% url 'vote:vote' election.pk %}">Vote Now!</a>
-      {% elif election.closed and not election.result_unpublished %}
+      {% elif election.closed and election.result_published %}
         <div class="alert alert-info" role="alert">
           <h4 class="alert-heading">Voting Ended:</h4>
           <hr>
@@ -79,7 +79,7 @@
           {% endif %}
           <div class="mt-3">
               <div class="row row-cols-1 row-cols-md-2 vote-list">
-                  {% for application in election.applications|shuffle %}
+                  {% for application in election.applications.all|shuffle %}
                       <div class="col mb-2">
                           <div class="applicant">
                               {% if application.avatar %}
diff --git a/vote/templates/vote/spectator_election_item.html b/vote/templates/vote/spectator_election_item.html
index ce68ec184c4ebe7c066fa5a6349372c4ae05aeb1..e2130ff57c00640efb529fc531d444da6cf75614 100644
--- a/vote/templates/vote/spectator_election_item.html
+++ b/vote/templates/vote/spectator_election_item.html
@@ -10,7 +10,7 @@
     {% endif %}
     <hr>
     <div class="list-group mt-3">
-      {% if election.closed and not election.result_unpublished %}
+      {% if election.closed and election.result_published %}
         <div class="alert alert-info" role="alert">
           <h4 class="alert-heading">Election result:</h4>
           <hr>
diff --git a/vote/templates/vote/vote.html b/vote/templates/vote/vote.html
index f055095442c7e8fbf6f59c568413c2de77578498..4d8ac08c7baa3263751b2b6da4737377731c1bf7 100644
--- a/vote/templates/vote/vote.html
+++ b/vote/templates/vote/vote.html
@@ -49,7 +49,7 @@
                         <thead class="thead-light">
                         <tr>
                             <th>{% if election.voters_self_apply %}Applicant{% else %}Option{% endif %}</th>
-                            {% if not election.disable_abstention %}
+                            {% if election.enable_abstention %}
                                 <th class="choice text-center">Abstention</th>
                             {% endif %}
                             <th class="choice text-center text-success">YES</th>
diff --git a/vote/tests.py b/vote/tests.py
index a0fe09335bd61463eaae03e3e80876478104e78c..48d990e09635903acd70012f403e262b0ddeaa7d 100644
--- a/vote/tests.py
+++ b/vote/tests.py
@@ -1,6 +1,11 @@
+from datetime import timedelta, datetime
+
 from django.test import TestCase
+from django.utils import timezone
+from freezegun import freeze_time
 
-from vote.models import Enc32, Voter, Session
+from vote.models import Election, Enc32, Voter, Session
+from vote.selectors import closed_elections, open_elections, published_elections, upcoming_elections
 
 
 class Enc32TestCase(TestCase):
@@ -21,6 +26,59 @@ class VoterTestCase(TestCase):
             self.assertEqual(raw_password, ret_password)
 
 
+class ElectionSelectorsTest(TestCase):
+    def test_election_selectors(self) -> None:
+        now = datetime(year=2021, month=4, day=1, tzinfo=timezone.get_fixed_timezone(5))
+        before = now - timedelta(seconds=5)
+        bbefore = now - timedelta(seconds=10)
+        after = now + timedelta(seconds=5)
+        freeze_time(now).start()
+
+        session = Session.objects.create(title="TEST")
+        # upcoming elections
+        all_upcoming = set()
+        all_upcoming.add(Election.objects.create(session=session))
+        all_upcoming.add(Election.objects.create(session=session, start_date=after))
+        # open elections
+        all_opened = set()
+        all_opened.add(Election.objects.create(session=session, start_date=now))
+        all_opened.add(Election.objects.create(session=session, start_date=before, end_date=after))
+        # published elections
+        all_published = set()
+        all_published.add(Election.objects.create(session=session, start_date=bbefore, end_date=before,
+                                                  result_published=True))
+        all_published.add(Election.objects.create(session=session, start_date=before, end_date=now,
+                                                  result_published=True))
+        # closed (not published) elections
+        all_closed = set()
+        all_closed.add(Election.objects.create(session=session, start_date=bbefore, end_date=before))
+        all_closed.add(Election.objects.create(session=session, start_date=before, end_date=now))
+
+        # test upcoming
+        upcoming = upcoming_elections(session)
+        self.assertEqual(all_upcoming, set(upcoming))
+        for e in upcoming:
+            self.assertTrue(not e.started and not e.closed and not e.is_open)
+
+        # test open
+        opened = open_elections(session)
+        self.assertEqual(all_opened, set(opened))
+        for e in opened:
+            self.assertTrue(e.started and not e.closed and e.is_open)
+
+        # test published
+        published = published_elections(session)
+        self.assertEqual(all_published, set(published))
+        for e in published:
+            self.assertTrue(e.started and e.closed and not e.is_open and e.result_published)
+
+        # test closed
+        closed = closed_elections(session)
+        self.assertEqual(all_closed, set(closed))
+        for e in closed:
+            self.assertTrue(e.started and e.closed and not e.is_open and not e.result_published)
+
+
 def gen_data():
     session = Session.objects.create(
         title='Test session'
diff --git a/vote/urls.py b/vote/urls.py
index 5900f5aa04cd95a31008c2cf205a96f476642599..5650bc055785dbb184ac7d43af1b2374522cc778 100644
--- a/vote/urls.py
+++ b/vote/urls.py
@@ -20,5 +20,5 @@ urlpatterns = [
     path('vote/<int:election_id>/apply', views.apply, name='apply'),
     path('vote/<int:election_id>/delete-own-application', views.delete_own_application, name='delete_own_application'),
     path('help', views.help_page, name='help'),
-    path('spectator/<str:uuid>', views.spectator, name='spectator')
+    path('spectator/<uuid:uuid>', views.spectator, name='spectator')
 ]
diff --git a/vote/views.py b/vote/views.py
index 04bc74d6604c7d1d9bd4b1c4bced1b6cd0ecbc1a..315d9b96dc5fc52e6cfaf86173f90f989192f68a 100644
--- a/vote/views.py
+++ b/vote/views.py
@@ -11,6 +11,7 @@ from ratelimit.decorators import ratelimit
 from vote.authentication import voter_login_required
 from vote.forms import AccessCodeAuthenticationForm, VoteForm, ApplicationUploadFormUser
 from vote.models import Election, Voter, Session
+from vote.selectors import open_elections, upcoming_elections, published_elections, closed_elections
 
 
 class LoginView(auth_views.LoginView):
@@ -57,32 +58,23 @@ def code_login(request, access_code=None):
 
 @voter_login_required
 def index(request):
-    voter = request.user
-    elections = [
-        (e, voter.can_vote(e), voter.application.filter(election=e).exists())
-        for e in voter.session.elections.order_by('pk')
-    ]
-
-    def date_asc(e):
-        date = e[0].start_date
-        return date.timestamp() if date else sys.maxsize
-
-    def date_desc(e):
-        date = e[0].start_date
-        return -date.timestamp() if date else -sys.maxsize
-
-    open_elections = sorted([e for e in elections if e[0].is_open], key=date_desc)
-    upcoming_elections = sorted([e for e in elections if not e[0].started], key=date_asc)
-    published_elections = sorted([e for e in elections if e[0].closed and not e[0].result_unpublished], key=date_desc)
-    closed_elections = sorted([e for e in elections if e[0].closed and e[0].result_unpublished], key=date_desc)
+    voter: Voter = request.user
+    session = voter.session
+
+    def list_elections(elections):
+        return [
+            (e, voter.can_vote(e), voter.has_applied(e))
+            for e in elections
+        ]
+
     context = {
-        'title': voter.session.title,
-        'meeting_link': voter.session.meeting_link,
+        'title': session.title,
+        'meeting_link': session.meeting_link,
         'voter': voter,
-        'open_elections': open_elections,
-        'upcoming_elections': upcoming_elections,
-        'published_elections': published_elections,
-        'closed_elections': closed_elections,
+        'open_elections': list_elections(open_elections(session)),
+        'upcoming_elections': list_elections(upcoming_elections(session)),
+        'published_elections': list_elections(published_elections(session)),
+        'closed_elections': list_elections(closed_elections(session)),
     }
 
     # overview
@@ -91,7 +83,7 @@ def index(request):
 
 @voter_login_required
 def vote(request, election_id):
-    voter = request.user
+    voter: Voter = request.user
     try:
         election = voter.session.elections.get(pk=election_id)
     except Election.DoesNotExist:
@@ -99,9 +91,9 @@ def vote(request, election_id):
 
     can_vote = voter.can_vote(election)
     if election.max_votes_yes is not None:
-        max_votes_yes = min(election.max_votes_yes, election.applications.count())
+        max_votes_yes = min(election.max_votes_yes, election.applications.all().count())
     else:
-        max_votes_yes = election.applications.count()
+        max_votes_yes = election.applications.all().count()
 
     context = {
         'title': election.title,
@@ -132,7 +124,7 @@ def apply(request, election_id):
                                                       ' currently not accepted')
         return redirect('vote:index')
 
-    application = voter.application.filter(election__id=election_id)
+    application = voter.applications.filter(election__id=election_id)
     instance = None
     if application.exists():
         instance = application.first()
@@ -158,7 +150,7 @@ def apply(request, election_id):
 def delete_own_application(request, election_id):
     voter = request.user
     election = get_object_or_404(voter.session.elections, pk=election_id)
-    application = voter.application.filter(election__id=election_id)
+    application = voter.applications.filter(election__id=election_id)
     if not election.can_apply:
         messages.add_message(request, messages.ERROR, 'Applications can currently not be deleted')
         return redirect('vote:index')
@@ -176,26 +168,13 @@ def help_page(request):
 
 def spectator(request, uuid):
     session = get_object_or_404(Session.objects, spectator_token=uuid)
-    elections = session.elections.all()
-
-    def date_asc(e):
-        date = e.start_date
-        return date.timestamp() if date else sys.maxsize
-
-    def date_desc(e):
-        date = e.start_date
-        return -date.timestamp() if date else -sys.maxsize
 
-    open_elections = sorted([e for e in elections if e.is_open], key=date_desc)
-    upcoming_elections = sorted([e for e in elections if not e.started], key=date_asc)
-    published_elections = sorted([e for e in elections if e.closed and int(e.result_published)], key=date_desc)
-    closed_elections = sorted([e for e in elections if e.closed and not int(e.result_published)], key=date_desc)
     context = {
         'title': session.title,
         'meeting_link': session.meeting_link,
-        'open_elections': open_elections,
-        'upcoming_elections': upcoming_elections,
-        'published_elections': published_elections,
-        'closed_elections': closed_elections,
+        'open_elections': open_elections(session),
+        'upcoming_elections': upcoming_elections(session),
+        'published_elections': published_elections(session),
+        'closed_elections': closed_elections(session),
     }
     return render(request, template_name='vote/spectator.html', context=context)