diff --git a/README.md b/README.md
index 9520227ca0d30537d670ed6a480888b89d9e44e9..991ae21abbe28100f8c9c3f5fecbc99b29268506 100644
--- a/README.md
+++ b/README.md
@@ -36,6 +36,7 @@ from djangoldp.models import Model
 class Todo(Model):
     name = models.CharField(max_length=255)
     deadline = models.DateTimeField()
+    
 
 ```
 
@@ -46,6 +47,7 @@ By default it will be "todos/" with an S for model called Todo
 <Model>._meta.container_path = "/my-path/"
 ```
 
+
 3.2. Configure field visibility (optional) 
 Note that at this stage you can limit access to certain fields of models using
 
@@ -134,14 +136,14 @@ list of ForeignKey, ManyToManyField, OneToOneField and their reverse relations.
 
 In the following example, besides the urls `/members/` and `/members/<pk>/`, two other will be added to serve a container of the skills of the member: `/members/<pk>/skills/` and `/members/<pk>/skills/<pk>/` 
 ```
-    url(r'^members/', LDPViewSet.urls(model=Member, nested_fields=("skills",))),
+   <Model>._meta.nested_fields=["skills"]
 ```
 
 From the 0.5 we added permissions check by default on every route, so you may encounter 400 errors code on your POST requests. You can disable those checks by specifying the permission_classes as an empty array in our URLs files.
 
 
 ```
-url(r'^posts/', LDPViewSet.urls(model=Post, permission_classes=(), filter_backends = ())),
+   <Model>.permissions_classes=[]
 ```
 
 ## Custom Meta options on models
@@ -150,6 +152,7 @@ url(r'^posts/', LDPViewSet.urls(model=Post, permission_classes=(), filter_backen
 ### auto_author
 This property allows to associate a model with the logged in user.
 
+
 ```python
 class MyModel(models.Model):
     author_user = models.ForeignKey(settings.AUTH_USER_MODEL)
@@ -158,7 +161,7 @@ class MyModel(models.Model):
 ```
 Now when an instance of `MyModel` is saved, its `author_user` property will be set to the current user. 
 
-## permissions
+## permissions_classes
 This allows you to add permissions for AnonymousUser, logged in user, author ... in the url:
 Currently, there are 3 choices :
 * ObjectPermission
@@ -173,15 +176,17 @@ AnonymousReadOnly gives these permissions:
 * Logged in users: can read all posts + create new posts
 * Author: can read all posts + create new posts + update their own
 
-```
-from django.conf.urls import url
-from djangoldp.views import LDPViewSet
-from djangoldp.permissions import AnonymousReadOnly
+```python
+from djangoldp.models import Model
+from djangoldp.permissions import AnonymousReadonly
+
+class Todo(Model):
+    name = models.CharField(max_length=255)
+    deadline = models.DateTimeField()
+    
+    class Meta:
+        permission_classes =  AnonymousReadonly
 
-urlpatterns = [
-    url(r'^projects/', ProjectViewSet.urls(permission_classes=(AnonymousReadOnly,))),
-    url(r'^customers/', LDPViewSet.urls(model=Customer)),
-]
 ```
 
 InboxPermissions is used for, well, notifications:
@@ -194,15 +199,49 @@ from django.conf.urls import url
 from djangoldp.views import LDPViewSet
 from djangoldp.permissions import NotificationsPermissions
 
-urlpatterns = [
-    url(r'^projects/', ProjectViewSet.urls(permission_classes=(InboxPermissions,))),
-    url(r'^customers/', LDPViewSet.urls(model=Customer)),
-]
+class Project(Model):
+    name = models.CharField(max_length=255)
+    deadline = models.DateTimeField()
+    
+    class Meta:
+        permission_classes =  InbcxPermissions
+
 ```
 
 Important note:
 If you need to give permissions to owner's object, don't forget to add auto_author in model's meta
 
+### view_set 
+In case of custom viewset, you can use 
+
+```
+from djangoldp.models import Model
+
+class Todo(Model):
+    name = models.CharField(max_length=255)
+    deadline = models.DateTimeField()
+    
+    class Meta:
+        view_set =  TodoViewSet
+
+```
+
+### container_path 
+See 3.1. Configure container path (optional)
+
+### serializer_fields 
+```
+from djangoldp.models import Model
+
+class Todo(Model):
+    name = models.CharField(max_length=255)
+    deadline = models.DateTimeField()
+    
+    class Meta:
+        serializer_fields =  ['name']
+
+```
+Only `name` will be serialized
 
 ## License
 
diff --git a/djangoldp/__init__.py b/djangoldp/__init__.py
index 790f02aa4e153fc4e9fbf41a833590d4bba23a5e..7deb3ab1dd665f79a867616966d6046d03968cad 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 += ('rdf_type', 'auto_author')
+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 c654e290f376d0e1b72148e326aef754a0acf595..66b5b17c796b09d5a3afa0273e1480159814b47d 100644
--- a/djangoldp/models.py
+++ b/djangoldp/models.py
@@ -7,7 +7,7 @@ class Model(models.Model):
 
     @classmethod
     def get_view_set(cls):
-        view_set = getattr(cls._meta, 'view_set', None)
+        view_set = getattr(cls._meta, 'view_set', getattr(cls.Meta, 'view_set', None))
         if view_set is None:
             from djangoldp.views import LDPViewSet
             view_set = LDPViewSet
@@ -15,7 +15,7 @@ class Model(models.Model):
 
     @classmethod
     def get_container_path(cls):
-        path = getattr(cls._meta, 'container_path', None)
+        path = getattr(cls._meta, 'container_path', getattr(cls.Meta, 'container_path', None))
         if path is None:
             path = "{}s".format(cls._meta.object_name.lower())
 
@@ -29,11 +29,15 @@ class Model(models.Model):
 
     @classmethod
     def resource_id(cls, instance):
+        return "{}{}".format(cls.container_id(instance), getattr(instance, cls.slug_field(instance)))
+
+    @classmethod
+    def slug_field(cls, instance):
         view_name = '{}-detail'.format(instance._meta.object_name.lower())
         slug_field = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][1][0])
         if slug_field.startswith('/'):
             slug_field = slug_field[1:]
-        return "{}{}".format(cls.container_id(instance), getattr(instance, slug_field))
+        return slug_field
 
     @classmethod
     def container_id(cls, instance):
@@ -50,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):
@@ -80,6 +86,14 @@ class Model(models.Model):
             path = "{}/".format(path)
         return path
 
+    @classmethod
+    def get_permission_classes(cls, related_model, default_permissions_classes):
+        try:
+            return getattr(related_model._meta, 'permission_classes',
+                           getattr(related_model.Meta, 'permission_classes', default_permissions_classes))
+        except AttributeError:
+            return default_permissions_classes
+
 
 class LDPSource(models.Model):
     container = models.URLField()
diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py
index a7fea8d2cc75537c1d426779faa98f99cd4626a7..8c78045479c84a2252e15f4041a7a5502f39b7bc 100644
--- a/djangoldp/serializers.py
+++ b/djangoldp/serializers.py
@@ -17,6 +17,7 @@ from rest_framework.utils import model_meta
 from rest_framework.utils.field_mapping import get_nested_relation_kwargs
 from rest_framework.utils.serializer_helpers import ReturnDict
 
+from djangoldp import permissions
 from djangoldp.fields import LDPUrlField, IdURLField
 from djangoldp.models import Model
 
@@ -29,7 +30,7 @@ class LDListMixin:
             pass
         if isinstance(data, dict):
             data = [data]
-        if isinstance(data, str) and str.startswith("http"):
+        if isinstance(data, str) and data.startswith("http"):
             data = [{'@id': data}]
         return [self.child.to_internal_value(item) for item in data]
 
@@ -45,7 +46,8 @@ class LDListMixin:
 
     def get_value(self, dictionary):
         try:
-            object_list = dictionary["@graph"]
+            object_list = dictionary['@graph']
+
             if self.parent.instance is None:
                 obj = next(filter(
                     lambda o: not hasattr(o, self.parent.url_field_name) or "./" in o[self.parent.url_field_name],
@@ -87,7 +89,14 @@ class LDListMixin:
 
             return ret
         except KeyError:
-            return super().get_value(dictionary)
+            obj = super().get_value(dictionary)
+            if isinstance(obj, dict) and self.parent.url_field_name in obj:
+                resource_id = obj[self.parent.url_field_name]
+                if isinstance(resource_id, str) and resource_id.startswith("_:"):
+                    object_list = self.root.initial_data['@graph']
+                    obj = [next(filter(lambda o: resource_id in o[self.parent.url_field_name], object_list))]
+
+            return obj
 
 
 class ContainerSerializer(LDListMixin, ListSerializer):
@@ -216,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
@@ -244,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:
@@ -298,7 +314,8 @@ class LDPSerializer(HyperlinkedModelSerializer):
 
                     try:
                         match = resolve(uri_to_iri(uri))
-                        ret['pk'] = match.kwargs['pk']
+                        slug_field = Model.slug_field(self.__class__.Meta.model)
+                        ret[slug_field] = match.kwargs[slug_field]
                     except Resolver404:
                         pass
 
@@ -311,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)
@@ -323,7 +350,7 @@ class LDPSerializer(HyperlinkedModelSerializer):
     def get_value(self, dictionary):
         try:
             object_list = dictionary["@graph"]
-            container_id = Model.container_path(self.parent.instance)
+            container_id = Model.container_id(self.parent.instance)
             obj = next(filter(lambda o: container_id in o[self.url_field_name], object_list))
             item = super().get_value(obj)
             full_item = None
@@ -349,12 +376,12 @@ 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):
+            if relation_info.to_many and relation_info.reverse and not (field_name in validated_data) and not field_name is None:
                 rel = getattr(instance._meta.model, field_name).rel
                 if rel.name in validated_data:
                     related = validated_data[rel.name]
@@ -380,9 +407,11 @@ class LDPSerializer(HyperlinkedModelSerializer):
 
         for attr, value in validated_data.items():
             if isinstance(value, dict):
+                slug_field = Model.slug_field(instance)
                 manager = getattr(instance, attr)
-                if 'pk' in value:
-                    oldObj = manager._meta.model.objects.get(pk=value['pk'])
+                if slug_field in value:
+                    kwargs = {slug_field: value[slug_field]}
+                    oldObj = manager._meta.model.objects.get(**kwargs)
                     value = self.update(instance=oldObj, validated_data=value)
                 else:
                     value = self.internal_create(validated_data=value, model=manager._meta.model)
@@ -397,18 +426,20 @@ class LDPSerializer(HyperlinkedModelSerializer):
     def save_or_update_nested_list(self, instance, nested_fields):
         for (field_name, data) in nested_fields:
             manager = getattr(instance, field_name)
+            slug_field = Model.slug_field(instance)
 
-            item_pk_to_keep = list(map(lambda e: int(e['pk']), filter(lambda x: 'pk' in x, data)))
+            item_pk_to_keep = list(map(lambda e: e[slug_field], filter(lambda x: slug_field in x, data)))
             for item in list(manager.all()):
-                if not item.pk in item_pk_to_keep:
+                if not str(getattr(item, slug_field)) in item_pk_to_keep:
                     if getattr(manager, 'through', None) is None:
                         item.delete()
                     else:
                         manager.remove(item)
 
             for item in data:
-                if 'pk' in item:
-                    oldObj = manager.model.objects.get(pk=item['pk'])
+                if slug_field in item:
+                    kwargs = {slug_field: item[slug_field]}
+                    oldObj = manager.model.objects.get(**kwargs)
                     savedItem = self.update(instance=oldObj, validated_data=item)
                 else:
                     rel = getattr(instance._meta.model, field_name).rel
diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py
index a68a803c1f26baa1bdb47ddd2c22706666b4c07f..e576eadb04959bfd632e5e0a075e0a5bf1d562d7 100644
--- a/djangoldp/tests/models.py
+++ b/djangoldp/tests/models.py
@@ -4,14 +4,25 @@ from django.db import models
 from djangoldp.models import Model
 
 
-class Skill(models.Model):
+class Skill(Model):
     title = models.CharField(max_length=255, blank=True, null=True)
     obligatoire = models.CharField(max_length=255)
+    slug = models.SlugField(blank=True, null=True, unique=True)
 
+    class Meta:
+        serializer_fields = ["@id", "title"]
+        lookup_field = 'slug'
 
-class JobOffer(models.Model):
+
+class JobOffer(Model):
     title = models.CharField(max_length=255, blank=True, null=True)
     skills = models.ManyToManyField(Skill, blank=True)
+    slug = models.SlugField(blank=True, null=True, unique=True)
+
+    class Meta:
+        nested_fields = ["skills"]
+        container_path = "job-offers/"
+        lookup_field = 'slug'
 
 
 class Thread(models.Model):
@@ -27,8 +38,33 @@ class Message(models.Model):
 
 class Dummy(models.Model):
     some = models.CharField(max_length=255, blank=True, null=True)
+    slug = models.SlugField(blank=True, null=True, unique=True)
 
 
 class LDPDummy(Model):
     some = models.CharField(max_length=255, blank=True, null=True)
 
+
+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')
+    title = models.CharField(max_length=255, blank=True, null=True)
+
+    class Meta:
+        serializer_fields = ['@id', 'title', 'invoice', 'tasks']
+        nested_fields = ["tasks"]
+
+
+class Task(models.Model):
+    batch = models.ForeignKey(Batch, on_delete=models.CASCADE, related_name='tasks')
+    title = models.CharField(max_length=255)
+
+    class Meta:
+        serializer_fields = ['@id', 'title', 'batch']
diff --git a/djangoldp/tests/tests_ldp_model.py b/djangoldp/tests/tests_ldp_model.py
index 329899c008d2d184eb9434b78d49ddf6ef8b702d..3e1da6a715f946324d464945551ff42ce2a38f82 100644
--- a/djangoldp/tests/tests_ldp_model.py
+++ b/djangoldp/tests/tests_ldp_model.py
@@ -11,7 +11,7 @@ class LDPModelTest(TestCase):
     def test_class_not_inheriting_ldp_model(self):
         dummy = Dummy.objects.create(some="text")
         self.assertEquals("/dummys/", Model.container_id(dummy))
-        self.assertEquals("/dummys/{}".format(dummy.pk), Model.resource_id(dummy))
+        self.assertEquals("/dummys/{}".format(dummy.slug), Model.resource_id(dummy))
 
     def test_class_inheriting_ldp_model(self):
         dummy = LDPDummy.objects.create(some="text")
@@ -21,8 +21,8 @@ class LDPModelTest(TestCase):
         self.assertEquals("/ldpdummys/{}".format(dummy.pk), Model.resource_id(dummy))
 
     def test_from_resolve_id(self):
-        saved_instance = Dummy.objects.create(some="text")
-        result = Model.resolve_id("/dummys/{}".format(saved_instance.pk))
+        saved_instance = Dummy.objects.create(some="text", slug="someid")
+        result = Model.resolve_id("/dummys/{}".format(saved_instance.slug))
         self.assertEquals(saved_instance, result)
 
     def test_resolve_container(self):
diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py
index 36f724bb19de040e21eac8d4204fc5a0ea39b5c7..276309990d48da4af68dee680d1bb8fa4e9bf13b 100644
--- a/djangoldp/tests/tests_save.py
+++ b/djangoldp/tests/tests_save.py
@@ -1,25 +1,59 @@
 from django.test import TestCase
 
 from djangoldp.serializers import LDPSerializer
-from djangoldp.tests.models import Skill, JobOffer
+from djangoldp.tests.models import Skill, JobOffer, Invoice
 
 
 class Save(TestCase):
 
+    def test_save_m2m_graph_with_many_nested(self):
+        invoice = {
+            "@graph": [
+                {
+                    "@id": "./",
+                    "batches": {"@id": "_:b381"},
+                    "title": "Nouvelle facture",
+                },
+                {
+                    "@id": "_:b381",
+                    "tasks": {"@id": "_:b382"},
+                    "title": "Batch 1"
+                },
+                {
+                    "@id": "_:b382",
+                    "title": "Tache 1"
+                }
+            ]
+        }
+
+        meta_args = {'model': Invoice, 'depth': 2, 'fields': ("@id", "title", "batches")}
+
+        meta_class = type('Meta', (), meta_args)
+        serializer_class = type(LDPSerializer)('InvoiceSerializer', (LDPSerializer,), {'Meta': meta_class})
+        serializer = serializer_class(data=invoice)
+        serializer.is_valid()
+        result = serializer.save()
+
+        self.assertEquals(result.title, "Nouvelle facture")
+        self.assertIs(result.batches.count(), 1)
+        self.assertEquals(result.batches.all()[0].title, "Batch 1")
+        self.assertIs(result.batches.all()[0].tasks.count(), 1)
+        self.assertEquals(result.batches.all()[0].tasks.all()[0].title, "Tache 1")
+
     def test_save_m2m(self):
-        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire")
-        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire")
+        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire", slug="slug1")
+        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire", slug="slug2")
 
         job = {"title": "job test",
                "skills": {
                    "ldp:contains": [
-                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.pk)},
-                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.pk), "title": "skill2 UP"},
-                       {"title": "skill3 NEW", "obligatoire": "obligatoire"},
+                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.slug)},
+                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.slug), "title": "skill2 UP"},
+                       {"title": "skill3", "obligatoire": "obligatoire", "slug": "slug3"},
                    ]}
                }
 
-        meta_args = {'model': JobOffer, 'depth': 1, 'fields': ("@id", "title", "skills")}
+        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})
@@ -31,15 +65,15 @@ class Save(TestCase):
         self.assertIs(result.skills.count(), 3)
         self.assertEquals(result.skills.all()[0].title, "skill1")  # no change
         self.assertEquals(result.skills.all()[1].title, "skill2 UP")  # title updated
-        self.assertEquals(result.skills.all()[2].title, "skill3 NEW")  # creation on the fly
+        self.assertEquals(result.skills.all()[2].title, "skill3")  # creation on the fly
 
     def test_save_m2m_graph_simple(self):
         job = {"@graph": [
-                   {"title": "job test",
-                    },
-               ]}
+            {"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})
@@ -61,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})
@@ -78,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})
@@ -96,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 39083e2038e831663e52137251f5cd9fec1fdfce..9d19ea9189fa5587153deb8f12063ddb17ff750f 100644
--- a/djangoldp/tests/tests_update.py
+++ b/djangoldp/tests/tests_update.py
@@ -8,23 +8,23 @@ from djangoldp.tests.models import Skill, JobOffer, Thread, Message
 class Update(TestCase):
 
     def test_update(self):
-        skill = Skill.objects.create(title="to drop", obligatoire="obligatoire")
-        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire")
-        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire")
+        skill = Skill.objects.create(title="to drop", obligatoire="obligatoire", slug="slug1")
+        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire", slug="slug2")
+        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire", slug="slug3")
         job1 = JobOffer.objects.create(title="job test")
         job1.skills.add(skill)
 
-        job = {"@id": "https://happy-dev.fr/job-offers/{}/".format(job1.pk),
+        job = {"@id": "https://happy-dev.fr/job-offers/{}/".format(job1.slug),
                "title": "job test updated",
                "skills": {
                    "ldp:contains": [
                        {"title": "new skill", "obligatoire": "okay"},
-                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.pk)},
-                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.pk), "title": "skill2 UP"},
+                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.slug)},
+                       {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.slug), "title": "skill2 UP"},
                    ]}
                }
 
-        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})
@@ -40,21 +40,21 @@ class Update(TestCase):
         self.assertEquals(skills[2].title, "skill2 UP")  # title updated
 
     def test_update_graph(self):
-        skill = Skill.objects.create(title="to drop", obligatoire="obligatoire")
-        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire")
-        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire")
-        job1 = JobOffer.objects.create(title="job test")
+        skill = Skill.objects.create(title="to drop", obligatoire="obligatoire", slug="slug1")
+        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire", slug="slug2")
+        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire", slug="slug3")
+        job1 = JobOffer.objects.create(title="job test", slug="slug4")
         job1.skills.add(skill)
 
         job = {"@graph":
             [
                 {
-                    "@id": "https://happy-dev.fr/job-offers/{}/".format(job1.pk),
+                    "@id": "https://happy-dev.fr/job-offers/{}/".format(job1.slug),
                     "title": "job test updated",
                     "skills": {
                         "ldp:contains": [
-                            {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.pk)},
-                            {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.pk)},
+                            {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.slug)},
+                            {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.slug)},
                             {"@id": "_.123"},
                         ]}
                 },
@@ -64,16 +64,16 @@ class Update(TestCase):
                     "obligatoire": "okay"
                 },
                 {
-                    "@id": "https://happy-dev.fr/skills/{}/".format(skill1.pk),
+                    "@id": "https://happy-dev.fr/skills/{}/".format(skill1.slug),
                 },
                 {
-                    "@id": "https://happy-dev.fr/skills/{}/".format(skill2.pk),
+                    "@id": "https://happy-dev.fr/skills/{}/".format(skill2.slug),
                     "title": "skill2 UP"
                 }
             ]
         }
 
-        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})
@@ -90,19 +90,19 @@ class Update(TestCase):
         self.assertEquals(skills[2].title, "skill2 UP")  # title updated
 
     def test_update_graph_2(self):
-        skill = Skill.objects.create(title="to drop", obligatoire="obligatoire")
-        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire")
-        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire")
-        job1 = JobOffer.objects.create(title="job test")
+        skill = Skill.objects.create(title="to drop", obligatoire="obligatoire", slug="slug")
+        skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire", slug="slug1")
+        skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire", slug="slug2")
+        job1 = JobOffer.objects.create(title="job test", slug="slug1")
         job1.skills.add(skill)
 
         job = {"@graph":
             [
                 {
-                    "@id": "https://happy-dev.fr/job-offers/{}/".format(job1.pk),
+                    "@id": "https://happy-dev.fr/job-offers/{}/".format(job1.slug),
                     "title": "job test updated",
                     "skills": {
-                        "@id": "https://happy-dev.fr/job-offers/{}/skills/".format(job1.pk)
+                        "@id": "https://happy-dev.fr/job-offers/{}/skills/".format(job1.slug)
                     }
                 },
                 {
@@ -111,24 +111,24 @@ class Update(TestCase):
                     "obligatoire": "okay"
                 },
                 {
-                    "@id": "https://happy-dev.fr/skills/{}/".format(skill1.pk),
+                    "@id": "https://happy-dev.fr/skills/{}/".format(skill1.slug),
                 },
                 {
-                    "@id": "https://happy-dev.fr/skills/{}/".format(skill2.pk),
+                    "@id": "https://happy-dev.fr/skills/{}/".format(skill2.slug),
                     "title": "skill2 UP"
                 },
                 {
-                    '@id': "https://happy-dev.fr/job-offers/{}/skills/".format(job1.pk),
+                    '@id': "https://happy-dev.fr/job-offers/{}/skills/".format(job1.slug),
                     "ldp:contains": [
-                        {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.pk)},
-                        {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.pk)},
+                        {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.slug)},
+                        {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.slug)},
                         {"@id": "_.123"},
                     ]
                 }
             ]
         }
 
-        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/tests/urls.py b/djangoldp/tests/urls.py
index 5062860e7ecfa04507fc3f8f5272efd3340108c4..7ac1c38f725a1f83c50bc1393bc37c28259f43b1 100644
--- a/djangoldp/tests/urls.py
+++ b/djangoldp/tests/urls.py
@@ -5,12 +5,10 @@ from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy
 from djangoldp.views import LDPViewSet
 
 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=())),
     url(r'^users/', LDPViewSet.urls(model=settings.AUTH_USER_MODEL, permission_classes=[])),
-    url(r'^dummys/', LDPViewSet.urls(model=Dummy, permission_classes=[])),
+    url(r'^dummys/', LDPViewSet.urls(model=Dummy, permission_classes=[], lookup_field='slug',)),
     url(r'^', include('djangoldp.urls')),
 ]
 
diff --git a/djangoldp/urls.py b/djangoldp/urls.py
index 3fc889b9564ebe67cb4ff16949ef6f3afaf06344..1dcce95e752cd2d96e8b62c6f2b5bcadf5ef2e4e 100644
--- a/djangoldp/urls.py
+++ b/djangoldp/urls.py
@@ -30,6 +30,7 @@ for class_name in model_classes:
     urls_fct = model_class.get_view_set().urls
     urlpatterns.append(url(r'^' + path, include(
         urls_fct(model=model_class,
-                 permission_classes=getattr(model_class._meta, 'permission_classes', []),
-                 fields=getattr(model_class._meta, 'serializer_fields', []),
-                 nested_fields=getattr(model_class._meta, 'nested_fields', [])))))
+                 lookup_field=getattr(model_class._meta, 'lookup_field', getattr(model_class.Meta, 'lookup_field', [])),
+                 permission_classes=getattr(model_class._meta, 'permission_classes', getattr(model_class.Meta, 'permission_classes', [])),
+                 fields=getattr(model_class._meta, 'serializer_fields', getattr(model_class.Meta, 'serializer_fields', [])),
+                 nested_fields=getattr(model_class._meta, 'nested_fields', getattr(model_class.Meta, 'nested_fields', []))))))
diff --git a/djangoldp/views.py b/djangoldp/views.py
index f3a084991efe20d4f692fa1c26d2b1c1cc5e1ca2..6b1e8ad5c1012fd75a35095037b3af110e6a4490 100644
--- a/djangoldp/views.py
+++ b/djangoldp/views.py
@@ -6,7 +6,6 @@ from django.core.urlresolvers import get_resolver
 from django.db.utils import OperationalError
 from django.shortcuts import get_object_or_404
 from django.utils.decorators import classonlymethod
-from djangoldp.models import LDPSource
 from guardian.shortcuts import get_objects_for_user
 from pyld import jsonld
 from rest_framework.authentication import SessionAuthentication
@@ -14,6 +13,7 @@ from rest_framework.parsers import JSONParser
 from rest_framework.renderers import JSONRenderer
 from rest_framework.viewsets import ModelViewSet
 
+from djangoldp.models import LDPSource, Model
 from .serializers import LDPSerializer
 
 
@@ -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,)
@@ -194,7 +194,8 @@ class LDPNestedViewSet(LDPViewSet):
             related_field=related_field,
             parent_lookup_field=cls.get_lookup_arg(**kwargs),
             model_prefix=cls.get_model(**kwargs)._meta.object_name.lower(),
-            permission_classes=kwargs.get('permission_classes', ()),
+            permission_classes=Model.get_permission_classes(related_field.related_model,
+                                                            kwargs.get('permission_classes', ())),
             lookup_url_kwarg=related_field.related_model._meta.object_name.lower() + '_id')