From ac81450e437cd26108068cd6e556b15b237690f2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Mon, 25 Feb 2019 14:57:44 +0100 Subject: [PATCH 1/6] update: auto generates routes (urls.py is not needed anymore) --- djangoldp/models.py | 26 +++++++++++++++++++++----- djangoldp/urls.py | 33 +++++++++++++++++++++++++++++++++ djangoldp/views.py | 2 +- 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 djangoldp/urls.py diff --git a/djangoldp/models.py b/djangoldp/models.py index 151cb7d8..f95d6c85 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -5,9 +5,26 @@ from django.urls import get_resolver class Model(models.Model): container_path = None + view_set = None + permission_classes = [] + fields = [] + nested_fields = [] - def get_container_path(self): - return self.container_path + @classmethod + def get_view_set(cls): + view_set = cls.view_set + if view_set is None: + from djangoldp.views import LDPViewSet + view_set = LDPViewSet + return view_set + + @classmethod + def get_container_path(cls): + path = cls.container_path + if path is None: + path = "{}s".format(cls._meta.object_name.lower()) + + return path def get_absolute_url(self): return Model.resource_id(self) @@ -26,9 +43,7 @@ class Model(models.Model): @classmethod def container_id(cls, instance): if isinstance(instance, cls): - path = instance.container_path - if path is None: - path = "{}s".format(instance._meta.object_name.lower()) + path = cls.get_container_path() else: view_name = '{}-list'.format(instance._meta.object_name.lower()) path = get_resolver().reverse(view_name) @@ -69,6 +84,7 @@ class Model(models.Model): path = "{}/".format(path) return path + class LDPSource(models.Model): container = models.URLField() federation = models.CharField(max_length=255) diff --git a/djangoldp/urls.py b/djangoldp/urls.py new file mode 100644 index 00000000..f7f22a0c --- /dev/null +++ b/djangoldp/urls.py @@ -0,0 +1,33 @@ +from importlib import import_module + +from django.conf import settings +from django.conf.urls import url, include + +from djangoldp.models import LDPSource, Model +from djangoldp.views import LDPSourceViewSet + + +def __clean_path(path): + if path.startswith("/"): + path = path[1:] + if not path.endswith("/"): + path = "{}/".format(path) + return path + + +urlpatterns = [ + url(r'^sources/', LDPSourceViewSet.urls(model=LDPSource)), +] + +for package in settings.DJANGOLDP_PACKAGES: + import_module('{}.models'.format(package)) + +model_classes = {cls.__name__: cls for cls in Model.__subclasses__()} + +for class_name in model_classes: + model_class = model_classes[class_name] + path = __clean_path(model_class.get_container_path()) + urls_fct = model_class.get_view_set().urls + urlpatterns.append(url(r'^' + path, include( + urls_fct(model=model_class, permission_classes=model_class.permission_classes, fields=model_class.fields, + nested_fields=model_class.nested_fields)))) diff --git a/djangoldp/views.py b/djangoldp/views.py index 3ccfdf73..a6e8c91b 100644 --- a/djangoldp/views.py +++ b/djangoldp/views.py @@ -6,6 +6,7 @@ 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 @@ -13,7 +14,6 @@ from rest_framework.parsers import JSONParser from rest_framework.renderers import JSONRenderer from rest_framework.viewsets import ModelViewSet -from .models import LDPSource from .serializers import LDPSerializer -- GitLab From a8dd5eaec1767a43c2bfacdb66d4512c9150a339 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 26 Feb 2019 15:13:43 +0100 Subject: [PATCH 2/6] update: fix tests --- djangoldp/models.py | 2 +- djangoldp/tests/runner.py | 1 + djangoldp/tests/tests_ldp_model.py | 3 +-- djangoldp/tests/urls.py | 11 ++++++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/djangoldp/models.py b/djangoldp/models.py index f95d6c85..0f96a36d 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -43,7 +43,7 @@ class Model(models.Model): @classmethod def container_id(cls, instance): if isinstance(instance, cls): - path = cls.get_container_path() + path = instance.get_container_path() else: view_name = '{}-list'.format(instance._meta.object_name.lower()) path = get_resolver().reverse(view_name) diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py index 70074c5b..7ecff27b 100644 --- a/djangoldp/tests/runner.py +++ b/djangoldp/tests/runner.py @@ -9,6 +9,7 @@ settings.configure(DEBUG=True, } }, ROOT_URLCONF='djangoldp.tests.urls', + DJANGOLDP_PACKAGES=['djangoldp'], INSTALLED_APPS=('django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', diff --git a/djangoldp/tests/tests_ldp_model.py b/djangoldp/tests/tests_ldp_model.py index 6400378c..329899c0 100644 --- a/djangoldp/tests/tests_ldp_model.py +++ b/djangoldp/tests/tests_ldp_model.py @@ -29,11 +29,10 @@ class LDPModelTest(TestCase): result = Model.resolve_container("/dummys/") self.assertEquals(Dummy, result) - @unittest.skip("futur feature: avoid urls.py on apps") def test_auto_url(self): from django.urls import get_resolver dummy = LDPDummy.objects.create(some="text") view_name = '{}-list'.format(dummy._meta.object_name.lower()) - path = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0], dummy.pk) + path = '/{}{}'.format(get_resolver().reverse_dict[view_name][0][0][0], dummy.pk) self.assertEquals(path, dummy.get_absolute_url()) diff --git a/djangoldp/tests/urls.py b/djangoldp/tests/urls.py index 392b0e2b..7dfbd980 100644 --- a/djangoldp/tests/urls.py +++ b/djangoldp/tests/urls.py @@ -1,9 +1,8 @@ from django.conf import settings +from django.conf.urls import url, include -from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy, LDPDummy +from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy from djangoldp.views import LDPViewSet -from django.conf.urls import url - urlpatterns = [ url(r'^skills/', LDPViewSet.urls(model=Skill, permission_classes=[], fields=["@id", "title"], nested_fields=[])), @@ -12,5 +11,7 @@ urlpatterns = [ 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'^ldp-dummys/', LDPViewSet.urls(model=LDPDummy, permission_classes=[])), -] \ No newline at end of file +] + +for package in settings.DJANGOLDP_PACKAGES: + urlpatterns.append(url(r'^', include('{}.urls'.format(package)))) -- GitLab From 1b8cceef3d388e23ddf3f1a77a33c081710dad6c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 26 Feb 2019 15:27:19 +0100 Subject: [PATCH 3/6] syntax: urls include simplification --- djangoldp/tests/urls.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/djangoldp/tests/urls.py b/djangoldp/tests/urls.py index 7dfbd980..5062860e 100644 --- a/djangoldp/tests/urls.py +++ b/djangoldp/tests/urls.py @@ -11,7 +11,6 @@ urlpatterns = [ 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'^', include('djangoldp.urls')), ] -for package in settings.DJANGOLDP_PACKAGES: - urlpatterns.append(url(r'^', include('{}.urls'.format(package)))) -- GitLab From 3dced943a0376bd5130a2ab2608bb437f9a4373f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 26 Feb 2019 15:34:24 +0100 Subject: [PATCH 4/6] update: urls section of the README --- README.md | 4 ++-- djangoldp/tests/runner.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 07ac1cf2..392fbe7f 100644 --- a/README.md +++ b/README.md @@ -68,12 +68,12 @@ from djangoldp.views import LDPViewSet from .models import Todo urlpatterns = [ - url(r'^todos/', LDPViewSet.urls(model=Todo)), + url(r'^', include('djangoldp.urls')), url(r'^admin/', admin.site.urls), ] ``` -This creates 2 routes, one for the list, and one with an ID listing the detail of an object. +This creates 2 routes for each Model, one for the list, and one with an ID listing the detail of an object. 5. In the settings.py file, add your application name at the beginning of the application list, and add the following lines diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py index 7ecff27b..47a4548b 100644 --- a/djangoldp/tests/runner.py +++ b/djangoldp/tests/runner.py @@ -9,7 +9,7 @@ settings.configure(DEBUG=True, } }, ROOT_URLCONF='djangoldp.tests.urls', - DJANGOLDP_PACKAGES=['djangoldp'], + DJANGOLDP_PACKAGES=['djangoldp.tests'], INSTALLED_APPS=('django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', -- GitLab From 535e1357c70e66c467d2f2e0ca90e719fc1e3135 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 26 Feb 2019 17:09:44 +0100 Subject: [PATCH 5/6] update: use _meta to put class fields --- djangoldp/models.py | 9 ++------- djangoldp/urls.py | 6 ++++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/djangoldp/models.py b/djangoldp/models.py index 0f96a36d..242dea66 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -4,15 +4,10 @@ from django.urls import get_resolver class Model(models.Model): - container_path = None - view_set = None - permission_classes = [] - fields = [] - nested_fields = [] @classmethod def get_view_set(cls): - view_set = cls.view_set + view_set = getattr(cls._meta, 'view_set', None) if view_set is None: from djangoldp.views import LDPViewSet view_set = LDPViewSet @@ -20,7 +15,7 @@ class Model(models.Model): @classmethod def get_container_path(cls): - path = cls.container_path + path = getattr(cls._meta, 'container_path', None) if path is None: path = "{}s".format(cls._meta.object_name.lower()) diff --git a/djangoldp/urls.py b/djangoldp/urls.py index f7f22a0c..3fc889b9 100644 --- a/djangoldp/urls.py +++ b/djangoldp/urls.py @@ -29,5 +29,7 @@ for class_name in model_classes: path = __clean_path(model_class.get_container_path()) urls_fct = model_class.get_view_set().urls urlpatterns.append(url(r'^' + path, include( - urls_fct(model=model_class, permission_classes=model_class.permission_classes, fields=model_class.fields, - nested_fields=model_class.nested_fields)))) + 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', []))))) -- GitLab From 753df5943efdedbe19f954e5d284588191cc1f1a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 26 Feb 2019 17:28:54 +0100 Subject: [PATCH 6/6] update: README --- README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 392fbe7f..316e9a27 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,19 @@ In the future it could also be used to auto configure django router (e.g. urls.p from djangoldp.models import Model class Todo(Model): - container_path = "/my-path/" name = models.CharField(max_length=255) deadline = models.DateTimeField() ``` -3.1. Configure field visibility (optional) +3.1. Configure container path (optional) +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 ``` @@ -69,12 +75,18 @@ from .models import Todo urlpatterns = [ url(r'^', include('djangoldp.urls')), - url(r'^admin/', admin.site.urls), + url(r'^admin/', admin.site.urls), # Optional ] ``` This creates 2 routes for each Model, one for the list, and one with an ID listing the detail of an object. +You could also only use this line in settings.py instead: + +``` +ROOT_URLCONF = 'djangoldp.urls' +``` + 5. In the settings.py file, add your application name at the beginning of the application list, and add the following lines ``` -- GitLab