Revert "Allow PDF variables to provide a bulk evaluation method (#3517)"

This reverts commit 6ada83df9a.
This commit is contained in:
Richard Schreiber
2023-08-14 15:11:13 +02:00
parent 83811c0343
commit ddc94a8a16
2 changed files with 6 additions and 77 deletions

View File

@@ -27,7 +27,6 @@ from decimal import Decimal
import pycountry import pycountry
from django.conf import settings from django.conf import settings
from django.core.files import File from django.core.files import File
from django.db import models
from django.db.models import F, Q from django.db.models import F, Q
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.timezone import now from django.utils.timezone import now
@@ -373,15 +372,11 @@ class PdfDataSerializer(serializers.Field):
self.context['vars_images'] = get_images(self.context['event']) self.context['vars_images'] = get_images(self.context['event'])
for k, f in self.context['vars'].items(): for k, f in self.context['vars'].items():
if 'evaluate_bulk' in f: try:
# Will be evaluated later by our list serializers res[k] = f['evaluate'](instance, instance.order, ev)
res[k] = (f['evaluate_bulk'], instance) except:
else: logger.exception('Evaluating PDF variable failed')
try: res[k] = '(error)'
res[k] = f['evaluate'](instance, instance.order, ev)
except:
logger.exception('Evaluating PDF variable failed')
res[k] = '(error)'
if not hasattr(ev, '_cached_meta_data'): if not hasattr(ev, '_cached_meta_data'):
ev._cached_meta_data = ev.meta_data ev._cached_meta_data = ev.meta_data
@@ -434,38 +429,6 @@ class PdfDataSerializer(serializers.Field):
return res return res
class OrderPositionListSerializer(serializers.ListSerializer):
def to_representation(self, data):
# We have a custom implementation of this method because PdfDataSerializer() might keep some elements unevaluated
# with a (callable, input) tuple. We'll loop over these entries and evaluate them bulk-wise to save on SQL queries.
if isinstance(self.parent, OrderSerializer) and isinstance(self.parent.parent, OrderListSerializer):
# Do not execute our custom code because it will be executed by OrderListSerializer later for the
# full result set.
return super().to_representation(data)
iterable = data.all() if isinstance(data, models.Manager) else data
data = []
evaluate_queue = defaultdict(list)
for item in iterable:
entry = self.child.to_representation(item)
if "pdf_data" in entry:
for k, v in entry["pdf_data"].items():
if isinstance(v, tuple) and callable(v[0]):
evaluate_queue[v[0]].append((v[1], entry, k))
data.append(entry)
for func, entries in evaluate_queue.items():
results = func([item for (item, entry, k) in entries])
for (item, entry, k), result in zip(entries, results):
entry["pdf_data"][k] = result
return data
class OrderPositionSerializer(I18nAwareModelSerializer): class OrderPositionSerializer(I18nAwareModelSerializer):
checkins = CheckinSerializer(many=True, read_only=True) checkins = CheckinSerializer(many=True, read_only=True)
answers = AnswerSerializer(many=True) answers = AnswerSerializer(many=True)
@@ -477,7 +440,6 @@ class OrderPositionSerializer(I18nAwareModelSerializer):
attendee_name = serializers.CharField(required=False) attendee_name = serializers.CharField(required=False)
class Meta: class Meta:
list_serializer_class = OrderPositionListSerializer
model = OrderPosition model = OrderPosition
fields = ('id', 'order', 'positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts', fields = ('id', 'order', 'positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts',
'company', 'street', 'zipcode', 'city', 'country', 'state', 'discount', 'company', 'street', 'zipcode', 'city', 'country', 'state', 'discount',
@@ -651,34 +613,6 @@ class OrderURLField(serializers.URLField):
}) })
class OrderListSerializer(serializers.ListSerializer):
def to_representation(self, data):
# We have a custom implementation of this method because PdfDataSerializer() might keep some elements
# unevaluated with a (callable, input) tuple. We'll loop over these entries and evaluate them bulk-wise to
# save on SQL queries.
iterable = data.all() if isinstance(data, models.Manager) else data
data = []
evaluate_queue = defaultdict(list)
for item in iterable:
entry = self.child.to_representation(item)
for p in entry.get("positions", []):
if "pdf_data" in p:
for k, v in p["pdf_data"].items():
if isinstance(v, tuple) and callable(v[0]):
evaluate_queue[v[0]].append((v[1], p, k))
data.append(entry)
for func, entries in evaluate_queue.items():
results = func([item for (item, entry, k) in entries])
for (item, entry, k), result in zip(entries, results):
entry["pdf_data"][k] = result
return data
class OrderSerializer(I18nAwareModelSerializer): class OrderSerializer(I18nAwareModelSerializer):
invoice_address = InvoiceAddressSerializer(allow_null=True) invoice_address = InvoiceAddressSerializer(allow_null=True)
positions = OrderPositionSerializer(many=True, read_only=True) positions = OrderPositionSerializer(many=True, read_only=True)
@@ -693,7 +627,6 @@ class OrderSerializer(I18nAwareModelSerializer):
class Meta: class Meta:
model = Order model = Order
list_serializer_class = OrderListSerializer
fields = ( fields = (
'code', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date', 'code', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads', 'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads',

View File

@@ -683,16 +683,12 @@ dictionaries as values that contain keys like in the following example::
"product": { "product": {
"label": _("Product name"), "label": _("Product name"),
"editor_sample": _("Sample product"), "editor_sample": _("Sample product"),
"evaluate": lambda orderposition, order, event: str(orderposition.item), "evaluate": lambda orderposition, order, event: str(orderposition.item)
"evaluate_bulk": lambda orderpositions: [str(op.item) for op in orderpositions],
} }
} }
The ``evaluate`` member will be called with the order position, order and event as arguments. The event might The ``evaluate`` member will be called with the order position, order and event as arguments. The event might
also be a subevent, if applicable. also be a subevent, if applicable.
The ``evaluate_bulk`` member is optional but can significantly improve performance in some situations because you
can perform database fetches in bulk instead of single queries for every position.
""" """