diff --git a/AKModel/forms.py b/AKModel/forms.py
index 43f712ed9614a6727abd8488620c7d1db953307d..8554efd9b65c5fc03dbf74960db7eaac5ac3505a 100644
--- a/AKModel/forms.py
+++ b/AKModel/forms.py
@@ -73,3 +73,27 @@ class NewEventWizardActivateForm(forms.ModelForm):
 
 class AdminIntermediateForm(forms.Form):
     pass
+
+
+class SlideExportForm(AdminIntermediateForm):
+    num_next = forms.IntegerField(
+        min_value=0,
+        max_value=6,
+        initial=3,
+        label=_("# next AKs"),
+        help_text=_("How many next AKs should be shown on a slide?"))
+    presentation_mode = forms.TypedChoiceField(
+        initial=False,
+        label=_("Presentation only?"),
+        widget=forms.RadioSelect,
+        choices=((True, _('Yes')), (False, _('No'))),
+        coerce=lambda x: x == "True",
+        help_text=_("Restrict AKs to those that asked for chance to be presented?"))
+    wish_notes = forms.TypedChoiceField(
+        initial=False,
+        label=_("Space for notes in wishes?"),
+        widget=forms.RadioSelect,
+        choices=((True, _('Yes')), (False, _('No'))),
+        coerce=lambda x: x == "True",
+        help_text=_("Create symbols indicating space to note down owners and timeslots for wishes, e.g., to be filled "
+                    "out on a touch screen while presenting?"))
diff --git a/AKModel/templates/admin/AKModel/status.html b/AKModel/templates/admin/AKModel/status.html
index 362c72406804e4973d9600363511aac46226bbe4..19d753c9b904ede318d23fd689e97f59c5c62447 100644
--- a/AKModel/templates/admin/AKModel/status.html
+++ b/AKModel/templates/admin/AKModel/status.html
@@ -89,9 +89,7 @@
                     <a class="btn btn-success"
                        href="{% url 'admin:ak_wiki_export' slug=event.slug %}">{% trans "Export AKs for Wiki" %}</a>
                     <a class="btn btn-success"
-                       href="{% url 'admin:ak_slide_export' event_slug=event.slug %}?num_next=3&wish_notes=False">{% trans "Export AK Slides" %}</a>
-                    <a class="btn btn-success"
-                       href="{% url 'admin:ak_slide_export' event_slug=event.slug %}?num_next=3&presentation_mode">{% trans "Export AK Slides (Presentation AKs only)" %}</a>
+                       href="{% url 'admin:ak_slide_export' event_slug=event.slug %}">{% trans "Export AK Slides" %}</a>
                 {% endif %}
 
                 <h3 class="block-header">{% trans "Requirements" %}</h3>
diff --git a/AKModel/urls.py b/AKModel/urls.py
index ca9cfe6745aa9321db95561536d1bc42cad13fb6..e86661fd425a8d8b9c35b4524d4a027d77118dfb 100644
--- a/AKModel/urls.py
+++ b/AKModel/urls.py
@@ -6,7 +6,7 @@ from rest_framework.routers import DefaultRouter
 from AKModel import views
 from AKModel.views import NewEventWizardStartView, NewEventWizardSettingsView, NewEventWizardPrepareImportView, \
     NewEventWizardImportView, NewEventWizardActivateView, NewEventWizardFinishView, EventStatusView, \
-    AKRequirementOverview, AKCSVExportView, AKWikiExportView, AKMessageDeleteView, export_slides
+    AKRequirementOverview, AKCSVExportView, AKWikiExportView, AKMessageDeleteView, ExportSlidesView
 
 api_router = DefaultRouter()
 api_router.register('akowner', views.AKOwnerViewSet, basename='AKOwner')
@@ -81,6 +81,5 @@ def get_admin_urls_event(admin_site):
              name="ak_wiki_export"),
         path('<slug:event_slug>/delete-orga-messages/', admin_site.admin_view(AKMessageDeleteView.as_view()),
              name="ak_delete_orga_messages"),
-        path('<slug:event_slug>/ak-slide-export/', export_slides, name="ak_slide_export"),
-
+        path('<slug:event_slug>/ak-slide-export/', ExportSlidesView.as_view(), name="ak_slide_export"),
     ]
diff --git a/AKModel/views.py b/AKModel/views.py
index 08f054f14f9812dbec9cf61db67703c700d92db0..530a26c5f9d0a9ab9ba6245a135e6fc995c0e74a 100644
--- a/AKModel/views.py
+++ b/AKModel/views.py
@@ -1,18 +1,18 @@
-from abc import ABC, abstractmethod
+import os
+import tempfile
 from itertools import zip_longest
 
 from django.contrib import admin, messages
-from django.contrib.admin.views.decorators import staff_member_required
-from django.http import HttpResponseRedirect
 from django.shortcuts import get_object_or_404, redirect
 from django.urls import reverse_lazy
 from django.utils.translation import gettext_lazy as _
 from django.views.generic import TemplateView, DetailView, ListView, DeleteView, CreateView, FormView, UpdateView
-from django_tex.shortcuts import render_to_pdf
+from django_tex.core import render_template_with_context, run_tex_in_directory
+from django_tex.response import PDFResponse
 from rest_framework import viewsets, permissions, mixins
 
 from AKModel.forms import NewEventWizardStartForm, NewEventWizardSettingsForm, NewEventWizardPrepareImportForm, \
-    NewEventWizardImportForm, NewEventWizardActivateForm, AdminIntermediateForm
+    NewEventWizardImportForm, NewEventWizardActivateForm, AdminIntermediateForm, SlideExportForm
 from AKModel.models import Event, AK, AKSlot, Room, AKTrack, AKCategory, AKOwner, AKOrgaMessage, AKRequirement
 from AKModel.serializers import AKSerializer, AKSlotSerializer, RoomSerializer, AKTrackSerializer, AKCategorySerializer, \
     AKOwnerSerializer
@@ -195,13 +195,12 @@ class AKWikiExportView(AdminViewMixin, DetailView):
         return context
 
 
-class IntermediateAdminView(AdminViewMixin, FormView, ABC):
+class IntermediateAdminView(AdminViewMixin, FormView):
     template_name = "admin/AKModel/action_intermediate.html"
     form_class = AdminIntermediateForm
 
-    @abstractmethod
     def get_preview(self):
-        pass
+        return ""
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
@@ -217,9 +216,6 @@ class AKMessageDeleteView(EventSlugMixin, IntermediateAdminView):
     def get_orga_messages_for_event(self, event):
         return AKOrgaMessage.objects.filter(ak__event=event)
 
-    def get_preview(self):
-        return None
-
     def get_success_url(self):
         return reverse_lazy('admin:event_status', kwargs={'slug': self.event.slug})
 
@@ -326,41 +322,50 @@ class NewEventWizardFinishView(WizardViewMixin, DetailView):
     wizard_step = 6
 
 
-@staff_member_required
-def export_slides(request, event_slug):
-    template_name = 'admin/AKModel/export/slides.tex'
-
-    event = get_object_or_404(Event, slug=event_slug)
-
-    NEXT_AK_LIST_LENGTH = int(request.GET["num_next"]) if "num_next" in request.GET else 3
-    RESULT_PRESENTATION_MODE = True if "presentation_mode" in request.GET else False
-    SPACE_FOR_NOTES_IN_WISHES = request.GET["wish_notes"] == "True" if "wish_notes" in request.GET else False
-
-    translations = {
-        'symbols': _("Symbols"),
-        'who': _("Who?"),
-        'duration': _("Duration(s)"),
-        'reso': _("Reso intention?"),
-        'category': _("Category (for Wishes)"),
-        'wishes': _("Wishes"),
-    }
-
-    def build_ak_list_with_next_aks(ak_list):
-        next_aks_list = zip_longest(*[ak_list[i + 1:] for i in range(NEXT_AK_LIST_LENGTH)], fillvalue=None)
-        return [(ak, next_aks) for ak, next_aks in zip_longest(ak_list, next_aks_list, fillvalue=list())]
-
-    categories_with_aks, ak_wishes = event.get_categories_with_aks(wishes_seperately=True, filter=lambda
-        ak: not RESULT_PRESENTATION_MODE or (ak.present or (ak.present is None and ak.category.present_by_default)))
-
-    context = {
-        'title': event.name,
-        'categories_with_aks': [(category, build_ak_list_with_next_aks(ak_list)) for category, ak_list in
-                                categories_with_aks],
-        'subtitle': _("AKs"),
-        "wishes": build_ak_list_with_next_aks(ak_wishes),
-        "translations": translations,
-        "result_presentation_mode": RESULT_PRESENTATION_MODE,
-        "space_for_notes_in_wishes": SPACE_FOR_NOTES_IN_WISHES,
-    }
-
-    return render_to_pdf(request, template_name, context, filename='slides.pdf')
+class ExportSlidesView(EventSlugMixin, IntermediateAdminView):
+    title = _('Export AK Slides')
+    form_class = SlideExportForm
+
+    def form_valid(self, form):
+        template_name = 'admin/AKModel/export/slides.tex'
+
+        NEXT_AK_LIST_LENGTH = form.cleaned_data['num_next']
+        RESULT_PRESENTATION_MODE = form.cleaned_data["presentation_mode"]
+        SPACE_FOR_NOTES_IN_WISHES = form.cleaned_data["wish_notes"]
+
+        translations = {
+            'symbols': _("Symbols"),
+            'who': _("Who?"),
+            'duration': _("Duration(s)"),
+            'reso': _("Reso intention?"),
+            'category': _("Category (for Wishes)"),
+            'wishes': _("Wishes"),
+        }
+
+        def build_ak_list_with_next_aks(ak_list):
+            next_aks_list = zip_longest(*[ak_list[i + 1:] for i in range(NEXT_AK_LIST_LENGTH)], fillvalue=None)
+            return [(ak, next_aks) for ak, next_aks in zip_longest(ak_list, next_aks_list, fillvalue=list())]
+
+        categories_with_aks, ak_wishes = self.event.get_categories_with_aks(wishes_seperately=True, filter=lambda
+            ak: not RESULT_PRESENTATION_MODE or (ak.present or (ak.present is None and ak.category.present_by_default)))
+
+        context = {
+            'title': self.event.name,
+            'categories_with_aks': [(category, build_ak_list_with_next_aks(ak_list)) for category, ak_list in
+                                    categories_with_aks],
+            'subtitle': _("AKs"),
+            "wishes": build_ak_list_with_next_aks(ak_wishes),
+            "translations": translations,
+            "result_presentation_mode": RESULT_PRESENTATION_MODE,
+            "space_for_notes_in_wishes": SPACE_FOR_NOTES_IN_WISHES,
+        }
+
+        source = render_template_with_context(template_name, context)
+
+        # Perform real compilation (run latex twice for correct page numbers)
+        with tempfile.TemporaryDirectory() as tempdir:
+            run_tex_in_directory(source, tempdir, template_name=self.template_name)
+            os.remove(f'{tempdir}/texput.tex')
+            pdf = run_tex_in_directory(source, tempdir, template_name=self.template_name)
+
+        return PDFResponse(pdf, filename='slides.pdf')
diff --git a/requirements.txt b/requirements.txt
index 2271a46748a00e2e888afe8e3930a83e915e1e08..5b8693e83e70dfa3367abf91b49e1c509afe9fa0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,7 +8,7 @@ django-simple-history==3.1.1
 django-registration-redux==2.11
 django-debug-toolbar==3.7.0
 django-bootstrap-datepicker-plus==3.0.5
-django-tex @ git+https://github.com/bhaettasch/django-tex.git@66cc6567acde4db2ac971b7707652067e664392c
+django-tex==1.1.10
 django-csp==3.7
 mysqlclient==2.0.3  # for production deployment
 pytz==2022.4