MixedAnswerListSerializer - wip

This commit is contained in:
Mira Weller
2026-09-30 21:03:27 +02:00
parent ae62a45a6a
commit 49ed8419bd
4 changed files with 59 additions and 12 deletions
+3 -3
View File
@@ -31,7 +31,7 @@ from rest_framework.exceptions import ValidationError
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.api.serializers.order import (
AnswerCreateSerializer, AnswerSerializer, InlineSeatSerializer,
AnswerCreateSerializer, AnswerSerializer, InlineSeatSerializer, MixedAnswerListSerializer,
)
from pretix.base.models import SalesChannel, Seat, Voucher
from pretix.base.models.orders import CartPosition
@@ -43,7 +43,7 @@ class TaxIncludedField(serializers.Field):
class CartPositionSerializer(I18nAwareModelSerializer):
answers = AnswerSerializer(many=True)
answers = MixedAnswerListSerializer(child=AnswerSerializer(), source='*')
seat = InlineSeatSerializer()
includes_tax = TaxIncludedField(source='*')
@@ -55,7 +55,7 @@ class CartPositionSerializer(I18nAwareModelSerializer):
class BaseCartPositionCreateSerializer(I18nAwareModelSerializer):
answers = AnswerCreateSerializer(many=True, required=False)
answers = MixedAnswerListSerializer(child=AnswerCreateSerializer(required=False), source='*', required=False)
attendee_name = serializers.CharField(required=False, allow_null=True)
includes_tax = serializers.BooleanField(required=False, allow_null=True)
+49 -4
View File
@@ -40,6 +40,7 @@ from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.relations import SlugRelatedField
from rest_framework.reverse import reverse
from rest_framework.serializers import ListSerializer
from pretix.api.auth.utils import get_session_key_for_api_request
from pretix.api.serializers import CompatDecimalField, CompatibleJSONField
@@ -47,7 +48,7 @@ from pretix.api.serializers.event import SubEventSerializer
from pretix.api.serializers.forms import form_field_to_serializer_field
from pretix.api.serializers.i18n import I18nAwareModelSerializer
from pretix.api.serializers.item import (
InlineItemVariationSerializer, ItemSerializer, DatafieldSerializer,
InlineItemVariationSerializer, ItemSerializer, DatafieldSerializer, cook_id, system_datafield_numbers, uncook_id,
)
from pretix.api.signals import order_api_details, orderposition_api_details
from pretix.base.decimal import round_decimal
@@ -57,7 +58,7 @@ from pretix.base.media import MEDIA_TYPES
from pretix.base.models import (
CachedFile, Checkin, Customer, Device, GiftCard, Invoice, InvoiceAddress,
InvoiceLine, Item, ItemVariation, Order, OrderPosition, Question,
QuestionAnswer, ReusableMedium, SalesChannel, Seat, SubEvent, TaxRule,
QuestionAnswer, QuestionnaireChild, ReusableMedium, SalesChannel, Seat, SubEvent, TaxRule,
Voucher,
)
from pretix.base.models.orders import (
@@ -229,6 +230,50 @@ class InlineSeatSerializer(I18nAwareModelSerializer):
fields = ('id', 'name', 'seat_guid', 'zone_name', 'row_name', 'row_label', 'seat_label', 'seat_number')
class MixedAnswerListSerializer(ListSerializer):
def __init__(self, instance=None, *args, **kwargs):
self.parent_instance = instance
super().__init__(instance.answers if instance else None, *args, **kwargs)
def get_value(self, dictionary):
return dictionary
def to_representation(self, instance):
answers = super().to_representation(instance.answers)
for qc in QuestionnaireChild.objects.filter(questionnaire__items__id=instance.item_id, system_datafield__isnull=False):
answers.append({
"question": cook_id(qc),
"answer": instance.get_system_answer(qc.system_datafield),
"question_identifier": f'@{qc.system_datafield}',
"options": [],
"option_identifiers": [],
"questionnaire_id": qc.questionnaire_id,
"system_datafield": qc.system_datafield,
})
return {
"answers": answers,
}
def to_internal_value(self, data):
result = {}
answers = []
for answer in data["answers"]:
try:
qid, dfid, sys_df = uncook_id(answer["question"])
except ValueError:
if type(answer["question"]) is str and answer["question"].lstrip("@") in system_datafield_numbers:
qid, dfid, sys_df = None, None, answer["question"].lstrip("@")
else:
raise
if dfid:
answer["question"] = dfid
answers.append(answer)
else:
result[sys_df] = Country(answer["answer"]) if sys_df == "country" else answer["answer"]
result["answers"] = super().to_internal_value(answers)
return result
class AnswerSerializer(I18nAwareModelSerializer):
question_identifier = AnswerQuestionIdentifierField(source='*', read_only=True)
option_identifiers = AnswerQuestionOptionsIdentifierField(source='*', read_only=True)
@@ -591,7 +636,7 @@ class OrderPositionPluginDataField(serializers.Field):
class OrderPositionSerializer(I18nAwareModelSerializer):
checkins = InlineCheckinSerializer(many=True, read_only=True)
print_logs = PrintLogSerializer(many=True, read_only=True)
answers = AnswerSerializer(many=True)
answers = MixedAnswerListSerializer(child=AnswerSerializer(), source='*')
downloads = PositionDownloadsField(source='*', read_only=True)
order = serializers.SlugRelatedField(slug_field='code', read_only=True)
pdf_data = PdfDataSerializer(source='*', read_only=True)
@@ -1041,7 +1086,7 @@ class OrderFeeCreateSerializer(I18nAwareModelSerializer):
class OrderPositionCreateSerializer(I18nAwareModelSerializer):
answers = AnswerCreateSerializer(many=True, required=False)
answers = MixedAnswerListSerializer(child=AnswerCreateSerializer(required=False), source='*', required=False)
addon_to = serializers.IntegerField(required=False, allow_null=True)
secret = serializers.CharField(required=False)
attendee_name = serializers.CharField(required=False, allow_null=True)
+3 -3
View File
@@ -30,7 +30,7 @@ from rest_framework.exceptions import ValidationError
from pretix.api.serializers.order import (
AnswerCreateSerializer, AnswerSerializer, CompatibleCountryField,
OrderFeeCreateSerializer, OrderPositionCreateSerializer,
MixedAnswerListSerializer, OrderFeeCreateSerializer, OrderPositionCreateSerializer,
)
from pretix.base.models import ItemVariation, Order, OrderFee, OrderPosition
from pretix.base.services.orders import OrderChangeManager, OrderError
@@ -41,7 +41,7 @@ logger = logging.getLogger(__name__)
class OrderPositionCreateForExistingOrderSerializer(OrderPositionCreateSerializer):
order = serializers.SlugRelatedField(slug_field='code', queryset=Order.objects.none(), required=True, allow_null=False)
answers = AnswerCreateSerializer(many=True, required=False)
answers = MixedAnswerListSerializer(child=AnswerCreateSerializer(required=False), source='*', required=False)
addon_to = serializers.IntegerField(required=False, allow_null=True)
secret = serializers.CharField(required=False)
attendee_name = serializers.CharField(required=False, allow_null=True)
@@ -154,7 +154,7 @@ class OrderFeeCreateForExistingOrderSerializer(OrderFeeCreateSerializer):
class OrderPositionInfoPatchSerializer(serializers.ModelSerializer):
answers = AnswerSerializer(many=True)
answers = MixedAnswerListSerializer(child=AnswerSerializer(), source='*')
country = CompatibleCountryField(source='*')
attendee_name = serializers.CharField(required=False)
+4 -2
View File
@@ -256,7 +256,7 @@ class OrderViewSetMixin:
[request.event],
Prefetch('meta_values', queryset=EventMetaValue.objects.select_related('property'),
to_attr='meta_values_cached'),
'questions',
'questionnaires',
'item_meta_properties',
)
return Prefetch(
@@ -287,7 +287,9 @@ class OrderViewSetMixin:
Prefetch('checkins', queryset=Checkin.objects.select_related('device')),
Prefetch('print_logs', queryset=PrintLog.objects.select_related('device')),
'item', 'variation',
Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related('options', 'question').order_by('question__position')),
Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related('options', 'question')
# TODO(questionnaires) .order_by('question__position')
),
'seat',
)
)