From 950cda47f197ef599385ad8dffa54ffbcb8f2df4 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste <bleme@pm.me>
Date: Tue, 12 Mar 2019 11:31:06 +0100
Subject: [PATCH] update: Allow to use Meta for _meta attributes

---
 README.md                 | 69 ++++++++++++++++++++++++++++++---------
 djangoldp/__init__.py     |  3 +-
 djangoldp/models.py       |  4 +--
 djangoldp/tests/models.py | 19 +++++++++++
 djangoldp/urls.py         |  6 ++--
 5 files changed, 80 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md
index 9520227c..991ae21a 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 790f02aa..13969406 100644
--- a/djangoldp/__init__.py
+++ b/djangoldp/__init__.py
@@ -1,4 +1,5 @@
 from django.db.models import options
 
 __version__ = '0.0.0'
-options.DEFAULT_NAMES += ('rdf_type', 'auto_author')
+options.DEFAULT_NAMES += (
+'rdf_type', 'auto_author', 'view_set', 'container_path', 'permission_classes', 'serializer_fields', 'nested_fields')
diff --git a/djangoldp/models.py b/djangoldp/models.py
index c654e290..fff174f8 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())
 
diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py
index a68a803c..981e5158 100644
--- a/djangoldp/tests/models.py
+++ b/djangoldp/tests/models.py
@@ -32,3 +32,22 @@ class Dummy(models.Model):
 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 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']
+
+
+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/urls.py b/djangoldp/urls.py
index 3fc889b9..59efe9c9 100644
--- a/djangoldp/urls.py
+++ b/djangoldp/urls.py
@@ -30,6 +30,6 @@ 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', [])))))
+                 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', []))))))
-- 
GitLab