From 6e107f8ef29103ff500f9808442ff5c335f48bc5 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste <bleme@pm.me>
Date: Mon, 18 Feb 2019 14:48:16 +0100
Subject: [PATCH 1/2] update: add test reproducing the issue 86

---
 djangoldp/serializers.py        |  1 -
 djangoldp/tests/models.py       | 10 ++++++++
 djangoldp/tests/tests_update.py | 41 ++++++++++++++++++++++++++++++++-
 djangoldp/tests/urls.py         |  4 +++-
 4 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py
index 4c00e52a..0ce94195 100644
--- a/djangoldp/serializers.py
+++ b/djangoldp/serializers.py
@@ -19,7 +19,6 @@ from rest_framework.utils.serializer_helpers import ReturnDict
 
 class LDListMixin:
     def to_internal_value(self, data):
-        # data = json.loads(data)
         try:
             data = data['ldp:contains']
         except (TypeError, KeyError):
diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py
index 968ffbbb..dab3dc1b 100644
--- a/djangoldp/tests/models.py
+++ b/djangoldp/tests/models.py
@@ -11,3 +11,13 @@ class JobOffer(models.Model):
     title = models.CharField(max_length=255, blank=True, null=True)
     skills = models.ManyToManyField(Skill, blank=True)
 
+
+class Thread(models.Model):
+    description = models.CharField(max_length=255, blank=True, null=True)
+
+
+class Message(models.Model):
+    text = models.CharField(max_length=255, blank=True, null=True)
+    thread = models.ForeignKey(Thread, on_delete=models.DO_NOTHING)
+
+
diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py
index b129716f..0adc7b5e 100644
--- a/djangoldp/tests/tests_update.py
+++ b/djangoldp/tests/tests_update.py
@@ -1,7 +1,7 @@
 from django.test import TestCase
 
 from djangoldp.serializers import LDPSerializer
-from djangoldp.tests.models import Skill, JobOffer
+from djangoldp.tests.models import Skill, JobOffer, Thread, Message
 
 
 class Serializer(TestCase):
@@ -134,3 +134,42 @@ class Serializer(TestCase):
             self.assertEquals(skills[0].title, "new skill")  # new skill
             self.assertEquals(skills[1].title, "skill1")  # no change
             self.assertEquals(skills[2].title, "skill2 UP")  # title updated
+
+    def test_update_list_with_reverse_relation(self):
+        thread = Thread.objects.create(description="Thread 1")
+        message1 = Message.objects.create(text="Message 1", thread=thread)
+        message2 = Message.objects.create(text="Message 2", thread=thread)
+
+
+        json = {"@graph": [
+                {"@id": "https://happy-dev.fr/messages/{}/".format(message1.pk),
+             "text": "Message 1 UP"
+                },
+                {"@id": "https://happy-dev.fr/messages/{}/".format(message2.pk),
+                 "text": "Message 2 UP"
+                },
+                {
+                 '@id': "https://happy-dev.fr/threads/{}/".format(thread.pk),
+                 'description': "Thread 1 UP",
+                 "message_set": [
+                     {"@id": "https://happy-dev.fr/messages/{}/".format(message1.pk)},
+                     {"@id": "https://happy-dev.fr/messages/{}/".format(message2.pk)},
+                 ]
+                 }
+                ]
+           }
+
+        meta_args = {'model': Thread, 'depth': 1, 'fields': ("@id", "description", "message_set" )}
+
+        meta_class = type('Meta', (), meta_args)
+        serializer_class = type(LDPSerializer)('ThreadSerializer', (LDPSerializer,), {'Meta': meta_class})
+        serializer = serializer_class(data=json, instance=thread)
+        serializer.is_valid()
+        result = serializer.save()
+
+        messages = result.message_set.all().order_by('text')
+
+        self.assertEquals(result.description, "Thread 1 UP")
+        self.assertIs(result.message_set.count(), 2)
+        self.assertEquals(messages[0].text, "Message 1 UP")
+        self.assertEquals(messages[1].title, "Message 2 UP")
diff --git a/djangoldp/tests/urls.py b/djangoldp/tests/urls.py
index 5982784d..eeb96677 100644
--- a/djangoldp/tests/urls.py
+++ b/djangoldp/tests/urls.py
@@ -1,4 +1,4 @@
-from djangoldp.tests.models import Skill, JobOffer
+from djangoldp.tests.models import Skill, JobOffer, Message, Thread
 from djangoldp.views import LDPViewSet
 from django.conf.urls import url
 
@@ -6,4 +6,6 @@ from django.conf.urls import url
 urlpatterns = [
     url(r'^skills/', LDPViewSet.urls(model=Skill, permission_classes=[], fields=["@id", "title"], nested_fields=[])),
     url(r'^job-offers/', LDPViewSet.urls(model=JobOffer, nested_fields=["skills"], permission_classes=())),
+    url(r'^messages/', LDPViewSet.urls(model=Message, permission_classes=[], fields=["@id", "text"], nested_fields=[])),
+    url(r'^threads/', LDPViewSet.urls(model=Thread, nested_fields=["message_set"], permission_classes=())),
 ]
\ No newline at end of file
-- 
GitLab


From 67c7eba4a10550684352d6c1e17eb65b72571243 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste <bleme@pm.me>
Date: Mon, 18 Feb 2019 14:51:29 +0100
Subject: [PATCH 2/2] bugfix: issue #86 by catching TypeError

---
 djangoldp/serializers.py        | 4 ++--
 djangoldp/tests/tests_update.py | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py
index 0ce94195..ae8b6b00 100644
--- a/djangoldp/serializers.py
+++ b/djangoldp/serializers.py
@@ -46,12 +46,12 @@ class LDListMixin:
             list = super().get_value(obj)
             try:
                 list = next(filter(lambda o: list['@id'] == o['@id'], object_list))
-            except KeyError:
+            except (KeyError, TypeError):
                 pass
 
             try:
                 list = list['ldp:contains']
-            except KeyError:
+            except (KeyError, TypeError):
                 pass
 
             if isinstance(list, dict):
diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py
index 0adc7b5e..e87360dd 100644
--- a/djangoldp/tests/tests_update.py
+++ b/djangoldp/tests/tests_update.py
@@ -172,4 +172,4 @@ class Serializer(TestCase):
         self.assertEquals(result.description, "Thread 1 UP")
         self.assertIs(result.message_set.count(), 2)
         self.assertEquals(messages[0].text, "Message 1 UP")
-        self.assertEquals(messages[1].title, "Message 2 UP")
+        self.assertEquals(messages[1].text, "Message 2 UP")
-- 
GitLab