diff --git a/doc/api/resources/orders.rst b/doc/api/resources/orders.rst index 443df60b3b..5f086fa7e3 100644 --- a/doc/api/resources/orders.rst +++ b/doc/api/resources/orders.rst @@ -1629,7 +1629,8 @@ Manipulating individual positions * ``answers``: If specified, you will need to provide **all** answers for this order position. Validation is handled the same way as when creating orders through the API. You are therefore expected to provide ``question``, ``answer``, and possibly ``options``. ``question_identifier`` - and ``option_identifiers`` will be ignored. + and ``option_identifiers`` will be ignored. As a special case, you can submit the magic value + ``"file:keep"`` as the answer to a file question to keep the current value without re-uploading it. **Example request**: diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py index a03448b774..1c3822d343 100644 --- a/src/pretix/api/serializers/order.py +++ b/src/pretix/api/serializers/order.py @@ -168,6 +168,8 @@ class AnswerSerializer(I18nAwareModelSerializer): return q def _handle_file_upload(self, data): + if data['answer'] == 'file:keep': + return data try: ao = self.context["request"].user or self.context["request"].auth cf = CachedFile.objects.get( @@ -439,6 +441,8 @@ class OrderPositionSerializer(I18nAwareModelSerializer): if isinstance(answ_data['answer'], File): a.file.save(answ_data['answer'].name, answ_data['answer'], save=False) a.answer = 'file://' + a.file.name + elif a.answer.startswith('file://') and answ_data['answer'] == "file:keep": + pass # keep current file else: for attr, value in answ_data.items(): setattr(a, attr, value) diff --git a/src/tests/api/test_orders.py b/src/tests/api/test_orders.py index ec140f1bde..43793c86a8 100644 --- a/src/tests/api/test_orders.py +++ b/src/tests/api/test_orders.py @@ -4951,6 +4951,7 @@ def test_position_update_question_handling(token_client, organizer, event, order ) assert r.status_code == 201 file_id_png = r.data['id'] + payload = { 'answers': [ { @@ -4971,3 +4972,24 @@ def test_position_update_question_handling(token_client, organizer, event, order answ = op.answers.get() assert answ.file assert answ.answer.startswith("file://") + + payload = { + 'answers': [ + { + "question": question.id, + "answer": "file:keep" + } + ] + } + question.type = Question.TYPE_FILE + question.save() + resp = token_client.patch( + '/api/v1/organizers/{}/events/{}/orderpositions/{}/'.format( + organizer.slug, event.slug, op.pk + ), format='json', data=payload + ) + assert resp.status_code == 200 + with scopes_disabled(): + answ = op.answers.get() + assert answ.file + assert answ.answer.startswith("file://")