From 62fb3d630f298ce053cbf38cd09b7f88410c3d2c Mon Sep 17 00:00:00 2001
From: Erwan Rouchet <rouchet@teklia.com>
Date: Mon, 19 Aug 2024 11:15:51 +0000
Subject: [PATCH] Support null values on image and polygon in CreateElement

---
 arkindex/documents/serializers/elements.py    |  2 ++
 .../documents/tests/test_create_elements.py   | 26 +++++++++++++++++++
 arkindex/project/serializer_fields.py         |  4 +++
 3 files changed, 32 insertions(+)

diff --git a/arkindex/documents/serializers/elements.py b/arkindex/documents/serializers/elements.py
index e8c014777a..67eeb6194e 100644
--- a/arkindex/documents/serializers/elements.py
+++ b/arkindex/documents/serializers/elements.py
@@ -693,6 +693,7 @@ class ElementCreateSerializer(ElementLightSerializer):
     image = serializers.PrimaryKeyRelatedField(
         queryset=Image.objects.using("default").all().select_related("server"),
         required=False,
+        allow_null=True,
         help_text="Link this element to an image by UUID via a polygon.",
         style={"base_template": "input.html"},
     )
@@ -704,6 +705,7 @@ class ElementCreateSerializer(ElementLightSerializer):
     )
     polygon = LinearRingField(
         required=False,
+        allow_null=True,
         help_text="Set the polygon linking this element to the image. "
                   "Either `image` must be set, or a `parent` element with an image must be set, to use a polygon. "
                   "Defaults to a rectangle taking up the whole image.",
diff --git a/arkindex/documents/tests/test_create_elements.py b/arkindex/documents/tests/test_create_elements.py
index d0baa1de54..7dee5d25fa 100644
--- a/arkindex/documents/tests/test_create_elements.py
+++ b/arkindex/documents/tests/test_create_elements.py
@@ -546,6 +546,32 @@ class TestCreateElements(FixtureAPITestCase):
                     "confidence": [expected_message]
                 })
 
+    def test_null_image_polygon(self):
+        """
+        Null values on `image` and `polygon` should be treated like the fields are absent from the payload
+        """
+        self.client.force_login(self.user)
+
+        with self.assertNumQueries(7):
+            response = self.client.post(
+                reverse("api:elements-create"),
+                {
+                    "corpus": str(self.corpus.id),
+                    "name": "Castle story",
+                    "type": "act",
+                    "image": None,
+                    "polygon": None,
+                },
+                format="json",
+            )
+            self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+
+        act = Element.objects.get(id=response.json()["id"])
+        self.assertEqual(act.name, "Castle story")
+        self.assertEqual(act.type, self.act_type)
+        self.assertIsNone(act.image_id)
+        self.assertIsNone(act.polygon)
+
     def test_worker_run_local(self):
         """
         A regular user can create an element with a WorkerRun of their own local process
diff --git a/arkindex/project/serializer_fields.py b/arkindex/project/serializer_fields.py
index 9a16ad4402..ae54759c6e 100644
--- a/arkindex/project/serializer_fields.py
+++ b/arkindex/project/serializer_fields.py
@@ -62,6 +62,10 @@ class LinearRingField(serializers.ListField):
     def run_validation(self, data):
         value = super().run_validation(data)
 
+        # Ignore nothingness
+        if value is None:
+            return
+
         # Ensure the LineString is closed
         if value[0] != value[-1]:
             value.append(value[0])
-- 
GitLab