From 245fb48989e3c53c023ecb9b0e2cb11786a3d7f9 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Fri, 28 Nov 2025 15:25:11 +0100 Subject: [PATCH] update media-API --- src/pretix/api/serializers/media.py | 31 +++++++++++++++++++++++++---- src/pretix/api/views/media.py | 8 +++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/pretix/api/serializers/media.py b/src/pretix/api/serializers/media.py index 8285fade48..cbfcbcf295 100644 --- a/src/pretix/api/serializers/media.py +++ b/src/pretix/api/serializers/media.py @@ -76,10 +76,21 @@ class ReusableMediaSerializer(I18nAwareModelSerializer): queryset=self.context['organizer'].issued_gift_cards.all() ) - if 'linked_orderposition' in self.context['request'].query_params.getlist('expand'): - self.fields['linked_orderposition'] = NestedOrderPositionSerializer(read_only=True) + # keep linked_orderposition (singular) for backwards compatibility, will be overwritten in self.validate + self.fields['linked_orderposition'] = serializers.PrimaryKeyRelatedField( + required=False, + allow_null=True, + queryset=OrderPosition.all.filter(order__event__organizer=self.context['organizer']), + ) + + if 'linked_orderposition' in self.context['request'].query_params.getlist('expand') or 'linked_orderpositions' in self.context['request'].query_params.getlist('expand'): + self.fields['linked_orderpositions'] = NestedOrderPositionSerializer( + many=True, + read_only=True + ) else: - self.fields['linked_orderposition'] = serializers.PrimaryKeyRelatedField( + self.fields['linked_orderpositions'] = serializers.PrimaryKeyRelatedField( + many=True, required=False, allow_null=True, queryset=OrderPosition.all.filter(order__event__organizer=self.context['organizer']), @@ -97,6 +108,10 @@ class ReusableMediaSerializer(I18nAwareModelSerializer): def validate(self, data): data = super().validate(data) + 'linked_orderposition': _('There are more than one linked_orderposition. You need to use linked_orderpositions.') + }) + data['linked_orderpositions'] = [linked_orderposition] + if 'type' in data and 'identifier' in data: qs = self.context['organizer'].reusable_media.filter( identifier=data['identifier'], type=data['type'] @@ -109,6 +124,14 @@ class ReusableMediaSerializer(I18nAwareModelSerializer): ) return data + def to_representation(self, obj): + r = super(ReusableMediaSerializer, self).to_representation(obj) + ops = r.get('linked_orderpositions') + if len(ops) < 2: + # add linked_orderposition (singular) for backwards compatibility + r['linked_orderposition'] = ops[0] if ops else None + return r + class Meta: model = ReusableMedium fields = ( @@ -121,7 +144,7 @@ class ReusableMediaSerializer(I18nAwareModelSerializer): 'active', 'expires', 'customer', - 'linked_orderposition', + 'linked_orderpositions', 'linked_giftcard', 'info', 'notes', diff --git a/src/pretix/api/views/media.py b/src/pretix/api/views/media.py index 1569ee2895..8b16a44da7 100644 --- a/src/pretix/api/views/media.py +++ b/src/pretix/api/views/media.py @@ -53,10 +53,12 @@ with scopes_disabled(): customer = django_filters.CharFilter(field_name='customer__identifier') updated_since = django_filters.IsoDateTimeFilter(field_name='updated', lookup_expr='gte') created_since = django_filters.IsoDateTimeFilter(field_name='created', lookup_expr='gte') + # backwards-compatible + linked_orderposition = django_filters.NumberFilter(field_name='linked_orderpositions__id') class Meta: model = ReusableMedium - fields = ['identifier', 'type', 'active', 'customer', 'linked_orderposition', 'linked_giftcard'] + fields = ['identifier', 'type', 'active', 'customer', 'linked_orderpositions', 'linked_giftcard'] class ReusableMediaViewSet(viewsets.ModelViewSet): @@ -75,7 +77,7 @@ class ReusableMediaViewSet(viewsets.ModelViewSet): ).order_by().values('card').annotate(s=Sum('value')).values('s') return self.request.organizer.reusable_media.prefetch_related( Prefetch( - 'linked_orderposition', + 'linked_orderpositions', queryset=OrderPosition.objects.select_related( 'order', 'order__event', 'order__event__organizer', 'seat', ).prefetch_related( @@ -155,7 +157,7 @@ class ReusableMediaViewSet(viewsets.ModelViewSet): type=s.validated_data["type"], identifier=s.validated_data["identifier"], ) - m.linked_orderposition = None # not relevant for cross-organizer + m.linked_orderpositions = None # not relevant for cross-organizer m.customer = None # not relevant for cross-organizer s = self.get_serializer(m) return Response({"result": s.data})