diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py
index eb8e42b21a..768a2985fa 100644
--- a/src/pretix/api/serializers/order.py
+++ b/src/pretix/api/serializers/order.py
@@ -129,12 +129,19 @@ class PdfDataSerializer(serializers.Field):
res = {}
ev = instance.subevent or instance.order.event
+ # This needs to have some extra performance improvements to avoid creating hundreds of queries when
+ # we serialize a list.
- pdfvars = get_variables(instance.order.event)
- for k, f in pdfvars.items():
+ if 'vars' not in self.context:
+ self.context['vars'] = get_variables(self.context['request'].event)
+
+ for k, f in self.context['vars'].items():
res[k] = f['evaluate'](instance, instance.order, ev)
- for k, v in ev.meta_data.items():
+ if not hasattr(ev, '_cached_meta_data'):
+ ev._cached_meta_data = ev.meta_data
+
+ for k, v in ev._cached_meta_data.items():
res['meta:' + k] = v
return res
diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py
index e18eebb1ad..b7ac7105de 100644
--- a/src/pretix/api/views/order.py
+++ b/src/pretix/api/views/order.py
@@ -3,7 +3,7 @@ import datetime
import django_filters
import pytz
from django.db import transaction
-from django.db.models import Q
+from django.db.models import Prefetch, Q
from django.db.models.functions import Concat
from django.http import FileResponse
from django.shortcuts import get_object_or_404
@@ -72,13 +72,34 @@ class OrderViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
return ctx
def get_queryset(self):
- return self.request.event.orders.prefetch_related(
- 'positions', 'positions__checkins', 'positions__item', 'positions__answers', 'positions__answers__options',
- 'positions__answers__question', 'fees', 'payments', 'refunds', 'refunds__payment'
+ qs = self.request.event.orders.prefetch_related(
+ 'fees', 'payments', 'refunds', 'refunds__payment'
).select_related(
'invoice_address'
)
+ if self.request.query_params.get('pdf_data', 'false') == 'true':
+ qs = qs.prefetch_related(
+ Prefetch(
+ 'positions',
+ OrderPosition.objects.all().prefetch_related(
+ 'checkins', 'item', 'variation', 'answers', 'answers__options', 'answers__question',
+ Prefetch('addons', OrderPosition.objects.select_related('item', 'variation'))
+ )
+ )
+ )
+ else:
+ qs = qs.prefetch_related(
+ Prefetch(
+ 'positions',
+ OrderPosition.objects.all().prefetch_related(
+ 'checkins', 'item', 'variation', 'answers', 'answers__options', 'answers__question',
+ )
+ )
+ )
+
+ return qs
+
def _get_output_provider(self, identifier):
responses = register_ticket_outputs.send(self.request.event)
for receiver, response in responses:
diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py
index 2347583fe8..475afa3033 100644
--- a/src/pretix/base/pdf.py
+++ b/src/pretix/base/pdf.py
@@ -161,7 +161,10 @@ DEFAULT_VARIABLES = OrderedDict((
"editor_sample": _("Addon 1\nAddon 2"),
"evaluate": lambda op, order, ev: "
".join([
'{} - {}'.format(p.item, p.variation) if p.variation else str(p.item)
- for p in op.addons.select_related('item', 'variation')
+ for p in (
+ op.addons.all() if 'addons' in op._prefetched_objects_cache
+ else op.addons.select_related('item', 'variation')
+ )
])
}),
("organizer", {
diff --git a/src/pretix/plugins/ticketoutputpdf/signals.py b/src/pretix/plugins/ticketoutputpdf/signals.py
index b54739ed97..a5a1c02368 100644
--- a/src/pretix/plugins/ticketoutputpdf/signals.py
+++ b/src/pretix/plugins/ticketoutputpdf/signals.py
@@ -36,10 +36,15 @@ def register_data(sender, **kwargs):
def get_answer(op, order, event, question_id):
try:
- a = op.answers.get(question_id=question_id)
+ if 'answers' in op._prefetched_objects_cache:
+ a = [a for a in op.answers.all() if a.question_id == question_id][0]
+ else:
+ a = op.answers.get(question_id=question_id)
return str(a).replace("\n", "
\n")
except QuestionAnswer.DoesNotExist:
return ""
+ except IndexError:
+ return ""
@receiver(layout_text_variables, dispatch_uid="pretix_ticketoutputpdf_layout_text_variables_questions")