From 6a4bafc79ffa9043ddb15ff698969cd0b3585dc3 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste <bleme@pm.me>
Date: Thu, 14 Mar 2019 15:22:02 +0100
Subject: [PATCH] update: depth and many_depth configurable on Model

---
 djangoldp/__init__.py           |  2 +-
 djangoldp/models.py             |  2 ++
 djangoldp/serializers.py        | 23 ++++++++++++++++++++---
 djangoldp/tests/models.py       | 17 ++++++++---------
 djangoldp/tests/tests_save.py   | 10 +++++-----
 djangoldp/tests/tests_update.py | 10 +++++-----
 djangoldp/views.py              |  4 ++--
 7 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/djangoldp/__init__.py b/djangoldp/__init__.py
index 8c3166a1..7deb3ab1 100644
--- a/djangoldp/__init__.py
+++ b/djangoldp/__init__.py
@@ -1,4 +1,4 @@
 from django.db.models import options
 
 __version__ = '0.0.0'
-options.DEFAULT_NAMES += ('lookup_field', 'rdf_type', 'rdf_context', 'auto_author', 'view_set', 'container_path', 'permission_classes', 'serializer_fields', 'nested_fields')
\ No newline at end of file
+options.DEFAULT_NAMES += ('lookup_field', 'rdf_type', 'rdf_context', 'auto_author', 'view_set', 'container_path', 'permission_classes', 'serializer_fields', 'nested_fields', 'depth', 'many_depth')
\ No newline at end of file
diff --git a/djangoldp/models.py b/djangoldp/models.py
index e8a79806..f08147cd 100644
--- a/djangoldp/models.py
+++ b/djangoldp/models.py
@@ -54,6 +54,8 @@ class Model(models.Model):
     class Meta:
         default_permissions = ('add', 'change', 'delete', 'view', 'control')
         abstract = True
+        depth = 1
+        many_depth = 0
 
     @classmethod
     def resolve_id(cls, id):
diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py
index f6a8c821..01163f53 100644
--- a/djangoldp/serializers.py
+++ b/djangoldp/serializers.py
@@ -225,6 +225,11 @@ class LDPSerializer(HyperlinkedModelSerializer):
 
         return data
 
+    def build_field(self, field_name, info, model_class, nested_depth):
+        nested_depth = self.compute_depth(nested_depth, model_class)
+
+        return super().build_field(field_name, info, model_class, nested_depth)
+
     def build_standard_field(self, field_name, model_field):
         class JSonLDStandardField:
             parent_view_name = None
@@ -253,6 +258,8 @@ class LDPSerializer(HyperlinkedModelSerializer):
         return type(field_class.__name__ + 'Valued', (JSonLDStandardField, field_class), {}), field_kwargs
 
     def build_nested_field(self, field_name, relation_info, nested_depth):
+        nested_depth = self.compute_depth(nested_depth, self.Meta.model)
+
         class NestedLDPSerializer(self.__class__):
 
             class Meta:
@@ -321,11 +328,21 @@ class LDPSerializer(HyperlinkedModelSerializer):
         kwargs['required'] = False
         return NestedLDPSerializer, kwargs
 
+    @classmethod
+    def compute_depth(cls, depth, model_class, name='depth'):
+        try:
+            model_depth = getattr(model_class._meta, 'depth', getattr(model_class.Meta, 'depth', 10))
+            depth = min(depth, int(model_depth))
+        except AttributeError:
+            depth = min(depth, int(getattr(model_class._meta, 'depth', 1)))
+
+        return depth
+
     @classmethod
     def many_init(cls, *args, **kwargs):
         kwargs['child'] = cls(**kwargs)
         try:
-            cls.Meta.depth = kwargs['context']['view'].many_depth
+            cls.Meta.depth = cls.compute_depth(kwargs['context']['view'].many_depth, cls.Meta.model, 'many_depth')
         except KeyError:
             pass
         return ContainerSerializer(*args, **kwargs)
@@ -359,9 +376,9 @@ class LDPSerializer(HyperlinkedModelSerializer):
         return instance
 
     def attach_related_object(self, instance, validated_data):
-        ModelClass = self.Meta.model
+        model_class = self.Meta.model
 
-        info = model_meta.get_field_info(ModelClass)
+        info = model_meta.get_field_info(model_class)
         many_to_many = {}
         for field_name, relation_info in info.relations.items():
             if relation_info.to_many and relation_info.reverse and not (field_name in validated_data):
diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py
index 43e56d66..e576eadb 100644
--- a/djangoldp/tests/models.py
+++ b/djangoldp/tests/models.py
@@ -1,7 +1,5 @@
 from django.conf import settings
 from django.db import models
-from django.db.models.signals import pre_save
-from django.dispatch import receiver
 
 from djangoldp.models import Model
 
@@ -11,9 +9,8 @@ class Skill(Model):
     obligatoire = models.CharField(max_length=255)
     slug = models.SlugField(blank=True, null=True, unique=True)
 
-
     class Meta:
-        serializer_fields=["@id", "title"]
+        serializer_fields = ["@id", "title"]
         lookup_field = 'slug'
 
 
@@ -23,8 +20,8 @@ class JobOffer(Model):
     slug = models.SlugField(blank=True, null=True, unique=True)
 
     class Meta:
-        nested_fields=["skills"]
-        container_path="job-offers/"
+        nested_fields = ["skills"]
+        container_path = "job-offers/"
         lookup_field = 'slug'
 
 
@@ -51,6 +48,10 @@ class LDPDummy(Model):
 class Invoice(Model):
     title = models.CharField(max_length=255, blank=True, null=True)
 
+    class Meta:
+        depth = 2
+        nested_fields = ["batches"]
+
 
 class Batch(Model):
     invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='batches')
@@ -58,6 +59,7 @@ class Batch(Model):
 
     class Meta:
         serializer_fields = ['@id', 'title', 'invoice', 'tasks']
+        nested_fields = ["tasks"]
 
 
 class Task(models.Model):
@@ -66,6 +68,3 @@ class Task(models.Model):
 
     class Meta:
         serializer_fields = ['@id', 'title', 'batch']
-
-
-
diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py
index 0d7b70b9..27630999 100644
--- a/djangoldp/tests/tests_save.py
+++ b/djangoldp/tests/tests_save.py
@@ -53,7 +53,7 @@ class Save(TestCase):
                    ]}
                }
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills", "slug")}
+        meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills", "slug")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('JobOfferSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -73,7 +73,7 @@ class Save(TestCase):
              },
         ]}
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills")}
+        meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('JobOfferSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -95,7 +95,7 @@ class Save(TestCase):
             {"@id": "_.123", "title": "skill3 NEW", "obligatoire": "obligatoire"},
         ]}
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills")}
+        meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('JobOfferSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -112,7 +112,7 @@ class Save(TestCase):
         skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire")
         job = {"title": "job test"}
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills")}
+        meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('JobOfferSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -130,7 +130,7 @@ class Save(TestCase):
         job = JobOffer.objects.create(title="job test")
         skill = {"title": "new SKILL"}
 
-        meta_args = {'model': Skill, 'depth': 1, 'fields': ("@id", "title")}
+        meta_args = {'model': Skill, 'depth': 2, 'fields': ("@id", "title")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('SkillSerializer', (LDPSerializer,), {'Meta': meta_class})
diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py
index 19c96eff..9d19ea91 100644
--- a/djangoldp/tests/tests_update.py
+++ b/djangoldp/tests/tests_update.py
@@ -24,7 +24,7 @@ class Update(TestCase):
                    ]}
                }
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills")}
+        meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('JobOfferSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -73,7 +73,7 @@ class Update(TestCase):
             ]
         }
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills")}
+        meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('JobOfferSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -128,7 +128,7 @@ class Update(TestCase):
             ]
         }
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills")}
+        meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('JobOfferSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -171,7 +171,7 @@ class Update(TestCase):
         ]
         }
 
-        meta_args = {'model': Thread, 'depth': 1, 'fields': ("@id", "description", "message_set")}
+        meta_args = {'model': Thread, 'depth': 2, 'fields': ("@id", "description", "message_set")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('ThreadSerializer', (LDPSerializer,), {'Meta': meta_class})
@@ -235,7 +235,7 @@ class Update(TestCase):
         ]
         }
 
-        meta_args = {'model': Thread, 'depth': 1, 'fields': ("@id", "description", "message_set")}
+        meta_args = {'model': Thread, 'depth': 2, 'fields': ("@id", "description", "message_set")}
 
         meta_class = type('Meta', (), meta_args)
         serializer_class = type(LDPSerializer)('ThreadSerializer', (LDPSerializer,), {'Meta': meta_class})
diff --git a/djangoldp/views.py b/djangoldp/views.py
index f3a08499..0af35f86 100644
--- a/djangoldp/views.py
+++ b/djangoldp/views.py
@@ -89,8 +89,8 @@ class LDPViewSet(LDPViewSetGenerator):
     """An automatically generated viewset that serves models following the Linked Data Platform convention"""
     fields = None
     exclude = None
-    depth = 1
-    many_depth = 0
+    depth = 2
+    many_depth = 1
     renderer_classes = (JSONLDRenderer,)
     parser_classes = (JSONLDParser,)
     authentication_classes = (NoCSRFAuthentication,)
-- 
GitLab