Reduce number of SQL queries in API order creation

This commit is contained in:
Raphael Michel
2022-06-13 12:05:14 +02:00
parent 635344a32f
commit 9b7088f7fc

View File

@@ -27,7 +27,9 @@ from decimal import Decimal
import django_filters import django_filters
import pytz import pytz
from django.db import transaction from django.db import transaction
from django.db.models import Exists, F, OuterRef, Prefetch, Q, Subquery from django.db.models import (
Exists, F, OuterRef, Prefetch, Q, Subquery, prefetch_related_objects,
)
from django.db.models.functions import Coalesce, Concat from django.db.models.functions import Coalesce, Concat
from django.http import FileResponse, HttpResponse from django.http import FileResponse, HttpResponse
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
@@ -202,13 +204,16 @@ class OrderViewSet(viewsets.ModelViewSet):
if 'invoice_address' not in self.request.GET.getlist('exclude'): if 'invoice_address' not in self.request.GET.getlist('exclude'):
qs = qs.select_related('invoice_address') qs = qs.select_related('invoice_address')
if self.request.query_params.get('include_canceled_positions', 'false') == 'true': qs = qs.prefetch_related(self._positions_prefetch(self.request))
return qs
def _positions_prefetch(self, request):
if request.query_params.get('include_canceled_positions', 'false') == 'true':
opq = OrderPosition.all opq = OrderPosition.all
else: else:
opq = OrderPosition.objects opq = OrderPosition.objects
if self.request.query_params.get('pdf_data', 'false') == 'true': if request.query_params.get('pdf_data', 'false') == 'true':
qs = qs.prefetch_related( return Prefetch(
Prefetch(
'positions', 'positions',
opq.all().prefetch_related( opq.all().prefetch_related(
Prefetch('checkins', queryset=Checkin.objects.all()), Prefetch('checkins', queryset=Checkin.objects.all()),
@@ -217,10 +222,8 @@ class OrderViewSet(viewsets.ModelViewSet):
Prefetch('addons', opq.select_related('item', 'variation', 'seat')) Prefetch('addons', opq.select_related('item', 'variation', 'seat'))
) )
) )
)
else: else:
qs = qs.prefetch_related( return Prefetch(
Prefetch(
'positions', 'positions',
opq.all().prefetch_related( opq.all().prefetch_related(
Prefetch('checkins', queryset=Checkin.objects.all()), Prefetch('checkins', queryset=Checkin.objects.all()),
@@ -229,9 +232,6 @@ class OrderViewSet(viewsets.ModelViewSet):
'seat', 'seat',
) )
) )
)
return qs
def _get_output_provider(self, identifier): def _get_output_provider(self, identifier):
responses = register_ticket_outputs.send(self.request.event) responses = register_ticket_outputs.send(self.request.event)
@@ -619,6 +619,7 @@ class OrderViewSet(viewsets.ModelViewSet):
serializer = SimulatedOrderSerializer(order, context=serializer.context) serializer = SimulatedOrderSerializer(order, context=serializer.context)
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
else: else:
prefetch_related_objects([order], self._positions_prefetch(request))
serializer = OrderSerializer(order, context=serializer.context) serializer = OrderSerializer(order, context=serializer.context)
order.log_action( order.log_action(