From 0b71322c05043c79f1ad3bcd038f4f6467ea245d Mon Sep 17 00:00:00 2001
From: Jean-Baptiste <bleme@pm.me>
Date: Tue, 15 Sep 2020 13:18:47 +0200
Subject: [PATCH] Do not exclude parent on nested fields

Fix https://git.startinblox.com/applications/hubl/issues/569
---
 djangoldp/tests/models.py     | 68 +++++++++++++++++------------------
 djangoldp/tests/runner.py     |  2 +-
 djangoldp/tests/tests_get.py  |  1 +
 djangoldp/tests/tests_save.py | 35 ++++++++++++++++++
 djangoldp/tests/tests_temp.py |  2 ++
 djangoldp/views.py            |  2 +-
 6 files changed, 74 insertions(+), 36 deletions(-)

diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py
index eb4d11be..42b99856 100644
--- a/djangoldp/tests/models.py
+++ b/djangoldp/tests/models.py
@@ -137,40 +137,6 @@ class PermissionlessDummy(Model):
         )
 
 
-class Invoice(Model):
-    title = models.CharField(max_length=255, blank=True, null=True)
-    date = models.DateField(blank=True, null=True)
-
-    class Meta(Model.Meta):
-        depth = 2
-        anonymous_perms = ['view']
-        authenticated_perms = ['inherit', 'add']
-        owner_perms = ['inherit', 'change', 'delete', 'control']
-
-
-class Batch(Model):
-    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='batches')
-    title = models.CharField(max_length=255, blank=True, null=True)
-
-    class Meta(Model.Meta):
-        serializer_fields = ['@id', 'title', 'invoice', 'tasks']
-        anonymous_perms = ['view', 'add']
-        authenticated_perms = ['inherit', 'add']
-        owner_perms = ['inherit', 'change', 'delete', 'control']
-        depth = 1
-
-
-class Task(models.Model):
-    batch = models.ForeignKey(Batch, on_delete=models.CASCADE, related_name='tasks')
-    title = models.CharField(max_length=255)
-
-    class Meta(Model.Meta):
-        serializer_fields = ['@id', 'title', 'batch']
-        anonymous_perms = ['view']
-        authenticated_perms = ['inherit', 'add']
-        owner_perms = ['inherit', 'change', 'delete', 'control']
-
-
 class Post(Model):
     content = models.CharField(max_length=255)
     author = models.ForeignKey(UserProfile, blank=True, null=True, on_delete=models.SET_NULL)
@@ -184,6 +150,16 @@ class Post(Model):
         authenticated_perms = ['inherit']
         owner_perms = ['inherit']
 
+class Invoice(Model):
+    title = models.CharField(max_length=255, blank=True, null=True)
+    date = models.DateField(blank=True, null=True)
+
+    class Meta(Model.Meta):
+        depth = 2
+        anonymous_perms = ['view']
+        authenticated_perms = ['inherit', 'add']
+        owner_perms = ['inherit', 'change', 'delete', 'control']
+
 
 class Circle(Model):
     name = models.CharField(max_length=255, blank=True)
@@ -199,6 +175,18 @@ class Circle(Model):
         depth = 1
 
 
+class Batch(Model):
+    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='batches')
+    title = models.CharField(max_length=255, blank=True, null=True)
+
+    class Meta(Model.Meta):
+        serializer_fields = ['@id', 'title', 'invoice', 'tasks']
+        anonymous_perms = ['view', 'add']
+        authenticated_perms = ['inherit', 'add']
+        owner_perms = ['inherit', 'change', 'delete', 'control']
+        depth = 1
+
+
 class CircleMember(Model):
     circle = models.ForeignKey(Circle, on_delete=models.CASCADE, related_name='members')
     user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="circles")
@@ -209,9 +197,21 @@ class CircleMember(Model):
         anonymous_perms = ['view', 'add', 'delete', 'add', 'change', 'control']
         authenticated_perms = ['inherit']
         unique_together = ['user', 'circle']
+        # serializer_fields = ['@id', 'user', 'circle']
         rdf_type = 'hd:circlemember'
 
 
+class Task(models.Model):
+    batch = models.ForeignKey(Batch, on_delete=models.CASCADE, related_name='tasks')
+    title = models.CharField(max_length=255)
+
+    class Meta(Model.Meta):
+        serializer_fields = ['@id', 'title', 'batch']
+        anonymous_perms = ['view']
+        authenticated_perms = ['inherit', 'add']
+        owner_perms = ['inherit', 'change', 'delete', 'control']
+
+
 class Project(Model):
     description = models.CharField(max_length=255, null=True, blank=False)
     team = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='projects')
diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py
index af89c6b8..32f99f73 100644
--- a/djangoldp/tests/runner.py
+++ b/djangoldp/tests/runner.py
@@ -25,7 +25,7 @@ failures = test_runner.run_tests([
     'djangoldp.tests.tests_pagination',
     'djangoldp.tests.tests_inbox',
     'djangoldp.tests.tests_backlinks_service',
-    #'djangoldp.tests.tests_temp'
+    # 'djangoldp.tests.tests_temp'
 ])
 if failures:
     sys.exit(failures)
diff --git a/djangoldp/tests/tests_get.py b/djangoldp/tests/tests_get.py
index a32a80bd..f2486a1a 100644
--- a/djangoldp/tests/tests_get.py
+++ b/djangoldp/tests/tests_get.py
@@ -88,6 +88,7 @@ class TestGET(APITestCase):
         self.assertEqual(response.status_code, 200)
         self.assertEquals(response.data['@id'], 'http://happy-dev.fr/invoices/{}/batches/'.format(invoice.pk))
         self.assertEquals(len(response.data['ldp:contains']), 2)
+        self.assertEquals(response.data['ldp:contains'][0]['invoice']['@id'], 'http://happy-dev.fr/invoices/{}/'.format(invoice.pk))
 
     def test_serializer_excludes(self):
         date = DateModel.objects.create(excluded='test', value=datetime.now())
diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py
index d1ab7b30..9d76073e 100644
--- a/djangoldp/tests/tests_save.py
+++ b/djangoldp/tests/tests_save.py
@@ -284,6 +284,41 @@ class Save(TestCase):
                          "http://testserver/resources/{}/".format(resource.pk))
         self.assertEqual(response.data['title'], "new job")
 
+    # Todo : why this test works without giving the parent (eg invoice) but test_nested_container_ter not working ?
+    def test_nested_container_bis(self):
+        invoice = Invoice.objects.create()
+        body = {
+            'http://happy-dev.fr/owl/#title': "new batch",
+        }
+
+        response = self.client.post('/invoices/{}/batches/'.format(invoice.pk),
+                                    data=json.dumps(body),
+                                    content_type='application/ld+json')
+        self.assertEqual(response.status_code, 201)
+        self.assertEqual(response.data['invoice']['@id'],
+                         "http://happy-dev.fr/invoices/{}/".format(invoice.pk))
+        self.assertEqual(response.data['title'], "new batch")
+
+    # Todo : why this test doesn't work without giving the parent (eg invoice) but test_nested_container_bis is working ?
+    def test_nested_container_ter(self):
+        circle = Circle.objects.create()
+        body = {
+            'user' : { # Todo : Should not be mandatory
+                "username" : "hubl-workaround-493"
+            },
+            'circle' : {}, # Todo : Should not be mandatory
+            '@context': {
+                "@vocab": "http://happy-dev.fr/owl/#",
+            }
+        }
+
+        response = self.client.post('/circles/{}/members/'.format(circle.pk),
+                                    data=json.dumps(body),
+                                    content_type='application/ld+json')
+        self.assertEqual(response.status_code, 201)
+        self.assertEqual(response.data['circle']['@id'],
+                         "http://testserver/circles/{}/".format(circle.pk))
+
     def test_nested_container_federated(self):
         resource = Resource.objects.create()
         body = {
diff --git a/djangoldp/tests/tests_temp.py b/djangoldp/tests/tests_temp.py
index db4dba08..bcac4c76 100644
--- a/djangoldp/tests/tests_temp.py
+++ b/djangoldp/tests/tests_temp.py
@@ -5,6 +5,7 @@ from django.test import TestCase
 from rest_framework.test import APIRequestFactory, APIClient
 
 from djangoldp.models import LDPSource
+from djangoldp.tests.models import Invoice, Circle
 
 
 class TestTemp(TestCase):
@@ -18,3 +19,4 @@ class TestTemp(TestCase):
     def tearDown(self):
         pass
 
+
diff --git a/djangoldp/views.py b/djangoldp/views.py
index 6e12304e..85dc48e0 100644
--- a/djangoldp/views.py
+++ b/djangoldp/views.py
@@ -548,7 +548,7 @@ class LDPNestedViewSet(LDPViewSet):
         return cls.urls(
             lookup_field=Model.get_meta(related_field.related_model, 'lookup_field', 'pk'),
             model=related_field.related_model,
-            exclude=(nested_related_name,) if related_field.one_to_many else (),
+            # exclude=(nested_related_name,) if related_field.one_to_many else (),
             parent_model=cls.get_model(**kwargs),
             nested_field=nested_field,
             nested_related_name=nested_related_name,
-- 
GitLab