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")