From d5190e036c831213b55d540119fa5f40b3f5da6f Mon Sep 17 00:00:00 2001
From: Jean-Baptiste <bleme@pm.me>
Date: Mon, 8 Jul 2019 22:08:48 +0200
Subject: [PATCH] update: Allow nullable nested field to be set as "empty
 string" on POST requests

---
 djangoldp/serializers.py      |  8 +++++++-
 djangoldp/tests/models.py     |  2 ++
 djangoldp/tests/tests_save.py | 26 ++++++++++++++++++++++++++
 djangoldp/tests/tests_temp.py | 30 ++++++++++++++++++++++++++++++
 4 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py
index b0450646..75940ba9 100644
--- a/djangoldp/serializers.py
+++ b/djangoldp/serializers.py
@@ -471,13 +471,19 @@ class LDPSerializer(HyperlinkedModelSerializer):
         nested_list_fields_name = list(filter(lambda key: isinstance(validated_data[key], list), validated_data))
         for field_name in nested_list_fields_name:
             nested_fields.append((field_name, validated_data.pop(field_name)))
-
+        validated_data = self.remove_empty_value(validated_data)
         instance = model.objects.create(**validated_data)
 
         self.save_or_update_nested_list(instance, nested_fields)
 
         return instance
 
+    def remove_empty_value(self, validated_data):
+        for attr, value in validated_data.items():
+            if value is '':
+                validated_data[attr] = None
+        return validated_data
+
     def update(self, instance, validated_data):
         nested_fields = []
         nested_fields_name = list(filter(lambda key: isinstance(validated_data[key], list), validated_data))
diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py
index d0d16a23..f3c6e88c 100644
--- a/djangoldp/tests/models.py
+++ b/djangoldp/tests/models.py
@@ -96,6 +96,8 @@ class Task(models.Model):
 class Post(Model):
     content = models.CharField(max_length=255)
     author = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True)
+    peer_user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name="peers_post")
+
 
     class Meta:
         auto_author = 'author'
diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py
index bb699bc6..d0acfadf 100644
--- a/djangoldp/tests/tests_save.py
+++ b/djangoldp/tests/tests_save.py
@@ -188,3 +188,29 @@ class Save(TestCase):
         self.assertNotIn('author', response.data)
         self.assertEquals(response.data['title'], "title")
         self.assertEquals(response.data['invoice']['title'], "title 3")
+
+    def test_post_should_accept_missing_field_id_nullable(self):
+        body = [
+            {
+                '@id': "./",
+                'http://happy-dev.fr/owl/#content': "post update",
+            }
+        ]
+        response = self.client.post('/posts/', data=json.dumps(body),
+                                    content_type='application/ld+json')
+        self.assertEqual(response.status_code, 201)
+        self.assertIn('peer_user', response.data)
+
+    def test_post_should_accept_empty_field_if_nullable(self):
+        body = [
+            {
+                '@id': "./",
+                'http://happy-dev.fr/owl/#content': "post update",
+                'http://happy-dev.fr/owl/#peer_user': ""
+            }
+        ]
+        response = self.client.post('/posts/', data=json.dumps(body),
+                                    content_type='application/ld+json')
+        self.assertEqual(response.status_code, 201)
+        self.assertEqual(response.data['peer_user'], None)
+
diff --git a/djangoldp/tests/tests_temp.py b/djangoldp/tests/tests_temp.py
index 578eb8a3..03dfb977 100644
--- a/djangoldp/tests/tests_temp.py
+++ b/djangoldp/tests/tests_temp.py
@@ -1,3 +1,6 @@
+import json
+
+from django.contrib.auth.models import User
 from django.test import TestCase
 from rest_framework.test import APIRequestFactory, APIClient
 
@@ -9,6 +12,33 @@ class TestTemp(TestCase):
     def setUp(self):
         self.factory = APIRequestFactory()
         self.client = APIClient()
+        self.user = User.objects.create_user(username='john', email='jlennon@beatles.com', password='glass onion')
+
 
     def tearDown(self):
         pass
+
+    def test_post_should_accept_missing_field_id_nullable(self):
+        body = [
+            {
+                '@id': "./",
+                'http://happy-dev.fr/owl/#content': "post update",
+            }
+        ]
+        response = self.client.post('/posts/', data=json.dumps(body),
+                                   content_type='application/ld+json')
+        self.assertEqual(response.status_code, 201)
+        self.assertIn('peer_user', response.data)
+
+    def test_post_should_accept_empty_field_if_nullable(self):
+        body = [
+            {
+                '@id': "./",
+                'http://happy-dev.fr/owl/#content': "post update",
+                'http://happy-dev.fr/owl/#peer_user': ""
+            }
+        ]
+        response = self.client.post('/posts/', data=json.dumps(body),
+                                   content_type='application/ld+json')
+        self.assertEqual(response.status_code, 201)
+        self.assertEqual(response.data['peer_user'], None)
-- 
GitLab