From dd4447d7b8955e627cba88909ebc59fffd19c441 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 19 Feb 2019 15:38:27 +0100 Subject: [PATCH 1/8] update: add failing tests for urls resolver feature --- djangoldp/models.py | 13 +++++++++++++ djangoldp/resolver.py | 17 +++++++++++++++++ djangoldp/tests/models.py | 10 ++++++++++ djangoldp/tests/runner.py | 1 + djangoldp/tests/tests_resolver.py | 25 +++++++++++++++++++++++++ djangoldp/tests/tests_save.py | 2 +- djangoldp/tests/tests_update.py | 2 +- djangoldp/tests/urls.py | 3 ++- 8 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 djangoldp/resolver.py create mode 100644 djangoldp/tests/tests_resolver.py diff --git a/djangoldp/models.py b/djangoldp/models.py index 50b31c6c..bcb62f61 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -1,6 +1,19 @@ from django.conf import settings from django.db import models + +class LDPModel(models.Model): + ldp_path = None + + def full_path(self): + return "{}/{}".format(self.container_path(), self.pk) + + def container_path(self): + return self.ldp_path + + class Meta: + abstract = True + class LDPSource(models.Model): container = models.URLField() federation = models.CharField(max_length=255) diff --git a/djangoldp/resolver.py b/djangoldp/resolver.py new file mode 100644 index 00000000..949ae3f1 --- /dev/null +++ b/djangoldp/resolver.py @@ -0,0 +1,17 @@ +class LDPResolver: + + @classmethod + def resource_url(cls, dummy): + pass + + @classmethod + def container_url(cls, dummy): + pass + + @classmethod + def resource_path(cls, dummy): + pass + + @classmethod + def container_path(cls, dummy): + pass diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py index 13a0aedf..29b0a521 100644 --- a/djangoldp/tests/models.py +++ b/djangoldp/tests/models.py @@ -1,6 +1,8 @@ from django.conf import settings from django.db import models +from djangoldp.models import LDPModel + class Skill(models.Model): title = models.CharField(max_length=255, blank=True, null=True) @@ -23,3 +25,11 @@ class Message(models.Model): author_user = models.ForeignKey(settings.AUTH_USER_MODEL) +class Dummy(models.Model): + some = models.CharField(max_length=255, blank=True, null=True) + + +class LDPDummy(LDPModel): + some = models.CharField(max_length=255, blank=True, null=True) + ldp_path = "ldp-dummys" + diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py index 1cf8604d..17419667 100644 --- a/djangoldp/tests/runner.py +++ b/djangoldp/tests/runner.py @@ -25,6 +25,7 @@ from django.test.runner import DiscoverRunner test_runner = DiscoverRunner(verbosity=1) failures = test_runner.run_tests([ + 'djangoldp.tests.tests_resolver', 'djangoldp.tests.tests_save', 'djangoldp.tests.tests_update']) if failures: diff --git a/djangoldp/tests/tests_resolver.py b/djangoldp/tests/tests_resolver.py new file mode 100644 index 00000000..55818f6d --- /dev/null +++ b/djangoldp/tests/tests_resolver.py @@ -0,0 +1,25 @@ +from django.test import TestCase + +from djangoldp.resolver import LDPResolver +from djangoldp.tests.models import Dummy, LDPDummy + + +class UrlUtils(TestCase): + + def test_class_not_inheriting_ldp_model(self): + dummy = Dummy.objects.create(some="text") + self.assertEquals("http://localhost/dummys/{}".format(dummy.pk), LDPResolver.resource_url(dummy)) + self.assertEquals("/dummys/{}".format(dummy.pk), LDPResolver.resource_path(dummy)) + self.assertEquals("http://localhost/dummys", LDPResolver.container_url(dummy)) + self.assertEquals("/dummys", LDPResolver.container_path(dummy)) + + def test_class_inheriting_ldp_model(self): + dummy = LDPDummy.objects.create(some="text") + self.assertEquals("http://localhost/ldp-dummys/{}".format(dummy.pk), LDPResolver.resource_url(dummy)) + self.assertEquals("/ldp-dummys/{}".format(dummy.pk), LDPResolver.resource_path(dummy)) + self.assertEquals("http://localhost/ldp-dummys/{}".format(dummy.pk), dummy.resource_url()) + self.assertEquals("/ldp-dummys/{}".format(dummy.pk), dummy.resource_path()) + self.assertEquals("http://localhost/ldp-dummys", LDPResolver.container_url(dummy)) + self.assertEquals("/ldp-dummys", LDPResolver.container_path(dummy)) + self.assertEquals("http://localhost/dummys/", dummy.container_url()) + self.assertEquals("/ldp-dummys", dummy.container_path()) diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py index 1117c928..7e05496a 100644 --- a/djangoldp/tests/tests_save.py +++ b/djangoldp/tests/tests_save.py @@ -4,7 +4,7 @@ from djangoldp.serializers import LDPSerializer from djangoldp.tests.models import Skill, JobOffer -class Serializer(TestCase): +class Save(TestCase): def test_save_m2m(self): skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire") diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py index 7b232b44..622b55ef 100644 --- a/djangoldp/tests/tests_update.py +++ b/djangoldp/tests/tests_update.py @@ -5,7 +5,7 @@ from djangoldp.serializers import LDPSerializer from djangoldp.tests.models import Skill, JobOffer, Thread, Message -class Serializer(TestCase): +class Update(TestCase): def test_update(self): skill = Skill.objects.create(title="to drop", obligatoire="obligatoire") diff --git a/djangoldp/tests/urls.py b/djangoldp/tests/urls.py index 0066129b..8e1cbc86 100644 --- a/djangoldp/tests/urls.py +++ b/djangoldp/tests/urls.py @@ -1,6 +1,6 @@ from django.conf import settings -from djangoldp.tests.models import Skill, JobOffer, Message, Thread +from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy from djangoldp.views import LDPViewSet from django.conf.urls import url @@ -11,4 +11,5 @@ urlpatterns = [ 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=[])), ] \ No newline at end of file -- GitLab From 9ed012911dba50263c4b57fa50d433e8dffe02c3 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 19 Feb 2019 16:10:03 +0100 Subject: [PATCH 2/8] feature: add LDPModel class to manage instance path resolution --- djangoldp/models.py | 35 +++++++++++++++++++++++++------ djangoldp/resolver.py | 17 --------------- djangoldp/tests/tests_resolver.py | 20 +++++++----------- 3 files changed, 36 insertions(+), 36 deletions(-) delete mode 100644 djangoldp/resolver.py diff --git a/djangoldp/models.py b/djangoldp/models.py index bcb62f61..abd9ea79 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -5,19 +5,41 @@ from django.db import models class LDPModel(models.Model): ldp_path = None - def full_path(self): - return "{}/{}".format(self.container_path(), self.pk) + def get_resource_path(self): + return LDPModel.resource_path(self) - def container_path(self): - return self.ldp_path + def get_container_path(self): + return LDPModel.container_path(self) + + @classmethod + def resource_path(cls, instance): + return "{}{}".format(LDPModel.container_path(instance), instance.pk) + + @classmethod + def container_path(cls, instance): + if isinstance(instance, cls): + path = instance.ldp_path + else: + from django.urls import get_resolver + view_name = '{}-list'.format(instance._meta.object_name.lower()) + path = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0], instance.pk) + + if not path.startswith("/"): + path = "/{}".format(path) + + if not path.endswith("/"): + path = "{}/".format(path) + + return path class Meta: abstract = True + class LDPSource(models.Model): container = models.URLField() federation = models.CharField(max_length=255) - + class Meta: rdf_type = 'sib:source' ordering = ('federation',) @@ -25,7 +47,7 @@ class LDPSource(models.Model): ('view_source', 'acl:Read'), ('control_source', 'acl:Control'), ) - + def __str__(self): return "{}: {}".format(self.federation, self.container) @@ -37,6 +59,7 @@ class LDNotification(models.Model): type = models.CharField(max_length=255) summary = models.TextField() date = models.DateTimeField(auto_now_add=True) + class Meta: permissions = ( ('view_todo', 'Read'), diff --git a/djangoldp/resolver.py b/djangoldp/resolver.py deleted file mode 100644 index 949ae3f1..00000000 --- a/djangoldp/resolver.py +++ /dev/null @@ -1,17 +0,0 @@ -class LDPResolver: - - @classmethod - def resource_url(cls, dummy): - pass - - @classmethod - def container_url(cls, dummy): - pass - - @classmethod - def resource_path(cls, dummy): - pass - - @classmethod - def container_path(cls, dummy): - pass diff --git a/djangoldp/tests/tests_resolver.py b/djangoldp/tests/tests_resolver.py index 55818f6d..96b1be0f 100644 --- a/djangoldp/tests/tests_resolver.py +++ b/djangoldp/tests/tests_resolver.py @@ -1,6 +1,6 @@ from django.test import TestCase -from djangoldp.resolver import LDPResolver +from djangoldp.models import LDPModel from djangoldp.tests.models import Dummy, LDPDummy @@ -8,18 +8,12 @@ class UrlUtils(TestCase): def test_class_not_inheriting_ldp_model(self): dummy = Dummy.objects.create(some="text") - self.assertEquals("http://localhost/dummys/{}".format(dummy.pk), LDPResolver.resource_url(dummy)) - self.assertEquals("/dummys/{}".format(dummy.pk), LDPResolver.resource_path(dummy)) - self.assertEquals("http://localhost/dummys", LDPResolver.container_url(dummy)) - self.assertEquals("/dummys", LDPResolver.container_path(dummy)) + self.assertEquals("/dummys/", LDPModel.container_path(dummy)) + self.assertEquals("/dummys/{}".format(dummy.pk), LDPModel.resource_path(dummy)) def test_class_inheriting_ldp_model(self): dummy = LDPDummy.objects.create(some="text") - self.assertEquals("http://localhost/ldp-dummys/{}".format(dummy.pk), LDPResolver.resource_url(dummy)) - self.assertEquals("/ldp-dummys/{}".format(dummy.pk), LDPResolver.resource_path(dummy)) - self.assertEquals("http://localhost/ldp-dummys/{}".format(dummy.pk), dummy.resource_url()) - self.assertEquals("/ldp-dummys/{}".format(dummy.pk), dummy.resource_path()) - self.assertEquals("http://localhost/ldp-dummys", LDPResolver.container_url(dummy)) - self.assertEquals("/ldp-dummys", LDPResolver.container_path(dummy)) - self.assertEquals("http://localhost/dummys/", dummy.container_url()) - self.assertEquals("/ldp-dummys", dummy.container_path()) + self.assertEquals("/ldp-dummys/", dummy.get_container_path()) + self.assertEquals("/ldp-dummys/{}".format(dummy.pk), dummy.get_resource_path()) + self.assertEquals("/ldp-dummys/", LDPModel.container_path(dummy)) + self.assertEquals("/ldp-dummys/{}".format(dummy.pk), LDPModel.resource_path(dummy)) -- GitLab From 99b3ca9b64011090c11bc49c7f28602732e3b8f7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 19 Feb 2019 16:18:33 +0100 Subject: [PATCH 3/8] syntax: add skipped test for the future "auto urls" feature --- djangoldp/tests/runner.py | 2 +- .../{tests_resolver.py => tests_ldp_model.py} | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) rename djangoldp/tests/{tests_resolver.py => tests_ldp_model.py} (64%) diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py index 17419667..4e3bcd04 100644 --- a/djangoldp/tests/runner.py +++ b/djangoldp/tests/runner.py @@ -25,7 +25,7 @@ from django.test.runner import DiscoverRunner test_runner = DiscoverRunner(verbosity=1) failures = test_runner.run_tests([ - 'djangoldp.tests.tests_resolver', + 'djangoldp.tests.tests_ldp_model', 'djangoldp.tests.tests_save', 'djangoldp.tests.tests_update']) if failures: diff --git a/djangoldp/tests/tests_resolver.py b/djangoldp/tests/tests_ldp_model.py similarity index 64% rename from djangoldp/tests/tests_resolver.py rename to djangoldp/tests/tests_ldp_model.py index 96b1be0f..0bf48e49 100644 --- a/djangoldp/tests/tests_resolver.py +++ b/djangoldp/tests/tests_ldp_model.py @@ -1,10 +1,12 @@ +import unittest + from django.test import TestCase from djangoldp.models import LDPModel from djangoldp.tests.models import Dummy, LDPDummy -class UrlUtils(TestCase): +class LDPModelTest(TestCase): def test_class_not_inheriting_ldp_model(self): dummy = Dummy.objects.create(some="text") @@ -17,3 +19,13 @@ class UrlUtils(TestCase): self.assertEquals("/ldp-dummys/{}".format(dummy.pk), dummy.get_resource_path()) self.assertEquals("/ldp-dummys/", LDPModel.container_path(dummy)) self.assertEquals("/ldp-dummys/{}".format(dummy.pk), LDPModel.resource_path(dummy)) + + + @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) + + self.assertEquals(path, dummy.get_resource_path()) -- GitLab From d7df4f31e188f27cf73265095c13f028e9d80146 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 19 Feb 2019 16:26:03 +0100 Subject: [PATCH 4/8] syntax: update readme for LDPModel and ldp_path --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e8525f1c..6dfacc1d 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,10 @@ django-admin startproject myldpserver 3. Create your django model inside a file myldpserver/myldpserver/models.py ``` -from django.db import models +from djangoldp.models import LDPModel -class Todo(models.Model): +class Todo(LDPModel): + ldp_path = "/my-path/" name = models.CharField(max_length=255) deadline = models.DateTimeField() -- GitLab From df0a759f9559d4a33f4efc0a91c5709493577022 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 19 Feb 2019 16:58:57 +0100 Subject: [PATCH 5/8] syntax: Refactor after code review --- README.md | 8 +++++--- djangoldp/models.py | 20 ++++++++++---------- djangoldp/tests/models.py | 6 +++--- djangoldp/tests/tests_ldp_model.py | 16 ++++++++-------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 6dfacc1d..17b3fabe 100644 --- a/README.md +++ b/README.md @@ -27,12 +27,14 @@ django-admin startproject myldpserver ``` 3. Create your django model inside a file myldpserver/myldpserver/models.py +Note that container_path will be use to resolve instance iri and container iri +In the future it could also be used to auto configure django router (e.g. urls.py) ``` -from djangoldp.models import LDPModel +from djangoldp.models import Model -class Todo(LDPModel): - ldp_path = "/my-path/" +class Todo(Model): + container_path = "/my-path/" name = models.CharField(max_length=255) deadline = models.DateTimeField() diff --git a/djangoldp/models.py b/djangoldp/models.py index abd9ea79..61d746a8 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -2,23 +2,23 @@ from django.conf import settings from django.db import models -class LDPModel(models.Model): - ldp_path = None +class Model(models.Model): + container_path = None - def get_resource_path(self): - return LDPModel.resource_path(self) + def get_absolute_url(self): + return Model.resource_id(self) - def get_container_path(self): - return LDPModel.container_path(self) + def get_container_id(self): + return Model.container_id(self) @classmethod - def resource_path(cls, instance): - return "{}{}".format(LDPModel.container_path(instance), instance.pk) + def resource_id(cls, instance): + return "{}{}".format(Model.container_id(instance), instance.pk) @classmethod - def container_path(cls, instance): + def container_id(cls, instance): if isinstance(instance, cls): - path = instance.ldp_path + path = instance.container_path else: from django.urls import get_resolver view_name = '{}-list'.format(instance._meta.object_name.lower()) diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py index 29b0a521..2622673f 100644 --- a/djangoldp/tests/models.py +++ b/djangoldp/tests/models.py @@ -1,7 +1,7 @@ from django.conf import settings from django.db import models -from djangoldp.models import LDPModel +from djangoldp.models import Model class Skill(models.Model): @@ -29,7 +29,7 @@ class Dummy(models.Model): some = models.CharField(max_length=255, blank=True, null=True) -class LDPDummy(LDPModel): +class LDPDummy(Model): some = models.CharField(max_length=255, blank=True, null=True) - ldp_path = "ldp-dummys" + container_path = "ldp-dummys" diff --git a/djangoldp/tests/tests_ldp_model.py b/djangoldp/tests/tests_ldp_model.py index 0bf48e49..8a17c88f 100644 --- a/djangoldp/tests/tests_ldp_model.py +++ b/djangoldp/tests/tests_ldp_model.py @@ -2,7 +2,7 @@ import unittest from django.test import TestCase -from djangoldp.models import LDPModel +from djangoldp.models import Model from djangoldp.tests.models import Dummy, LDPDummy @@ -10,15 +10,15 @@ class LDPModelTest(TestCase): def test_class_not_inheriting_ldp_model(self): dummy = Dummy.objects.create(some="text") - self.assertEquals("/dummys/", LDPModel.container_path(dummy)) - self.assertEquals("/dummys/{}".format(dummy.pk), LDPModel.resource_path(dummy)) + self.assertEquals("/dummys/", Model.container_id(dummy)) + self.assertEquals("/dummys/{}".format(dummy.pk), Model.resource_id(dummy)) def test_class_inheriting_ldp_model(self): dummy = LDPDummy.objects.create(some="text") - self.assertEquals("/ldp-dummys/", dummy.get_container_path()) - self.assertEquals("/ldp-dummys/{}".format(dummy.pk), dummy.get_resource_path()) - self.assertEquals("/ldp-dummys/", LDPModel.container_path(dummy)) - self.assertEquals("/ldp-dummys/{}".format(dummy.pk), LDPModel.resource_path(dummy)) + self.assertEquals("/ldp-dummys/", dummy.get_container_id()) + self.assertEquals("/ldp-dummys/{}".format(dummy.pk), dummy.get_absolute_url()) + self.assertEquals("/ldp-dummys/", Model.container_id(dummy)) + self.assertEquals("/ldp-dummys/{}".format(dummy.pk), Model.resource_id(dummy)) @unittest.skip("futur feature: avoid urls.py on apps") @@ -28,4 +28,4 @@ class LDPModelTest(TestCase): view_name = '{}-list'.format(dummy._meta.object_name.lower()) path = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0], dummy.pk) - self.assertEquals(path, dummy.get_resource_path()) + self.assertEquals(path, dummy.get_absolute_url()) -- GitLab From 9ee2a8502c3f3bc6fa5405797b9ab1db21a83c6d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Tue, 19 Feb 2019 17:35:38 +0100 Subject: [PATCH 6/8] update: manage slug on custom model --- djangoldp/models.py | 13 ++++++++++--- djangoldp/serializers.py | 2 +- djangoldp/tests/urls.py | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/djangoldp/models.py b/djangoldp/models.py index 61d746a8..00c63943 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -1,10 +1,14 @@ from django.conf import settings from django.db import models +from django.urls import get_resolver class Model(models.Model): container_path = None + def get_container_path(self): + return self.container_path + def get_absolute_url(self): return Model.resource_id(self) @@ -13,16 +17,19 @@ class Model(models.Model): @classmethod def resource_id(cls, instance): - return "{}{}".format(Model.container_id(instance), instance.pk) + 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(Model.container_id(instance), getattr(instance, slug_field)) @classmethod def container_id(cls, instance): if isinstance(instance, cls): path = instance.container_path else: - from django.urls import get_resolver view_name = '{}-list'.format(instance._meta.object_name.lower()) - path = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0], instance.pk) + path = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0]) if not path.startswith("/"): path = "/{}".format(path) diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py index 815be906..a2d0f6dc 100644 --- a/djangoldp/serializers.py +++ b/djangoldp/serializers.py @@ -41,7 +41,7 @@ class LDListMixin: try: object_list = dictionary["@graph"] view_name = '{}-list'.format(self.parent.Meta.model._meta.object_name.lower()) - part_id = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0], self.parent.instance.pk) + part_id = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0]) obj = next(filter(lambda o: part_id in o['@id'], object_list)) list = super().get_value(obj) try: diff --git a/djangoldp/tests/urls.py b/djangoldp/tests/urls.py index 8e1cbc86..392b0e2b 100644 --- a/djangoldp/tests/urls.py +++ b/djangoldp/tests/urls.py @@ -1,6 +1,6 @@ from django.conf import settings -from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy +from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy, LDPDummy from djangoldp.views import LDPViewSet from django.conf.urls import url @@ -12,4 +12,5 @@ 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 -- GitLab From 3908a5e118d2fc26a34d623a6a1ab4b2066a0a1f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Wed, 20 Feb 2019 11:53:37 +0100 Subject: [PATCH 7/8] update: add resolve functions on Model --- djangoldp/models.py | 39 ++++++++++++++++++++++++------ djangoldp/tests/tests_ldp_model.py | 8 ++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/djangoldp/models.py b/djangoldp/models.py index 00c63943..f63ffd4b 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -21,7 +21,7 @@ class Model(models.Model): slug_field = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][1][0]) if slug_field.startswith('/'): slug_field = slug_field[1:] - return "{}{}".format(Model.container_id(instance), getattr(instance, slug_field)) + return "{}{}".format(cls.container_id(instance), getattr(instance, slug_field)) @classmethod def container_id(cls, instance): @@ -29,19 +29,44 @@ class Model(models.Model): path = instance.container_path else: view_name = '{}-list'.format(instance._meta.object_name.lower()) - path = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0]) + path = get_resolver().reverse(view_name) - if not path.startswith("/"): - path = "/{}".format(path) - - if not path.endswith("/"): - path = "{}/".format(path) + path = cls.__clean_path(path) return path class Meta: abstract = True + @classmethod + def resolve_id(cls, id): + id = cls.__clean_path(id) + view, args, kwargs = get_resolver().resolve(id) + return view.initkwargs['model'].objects.get(**kwargs) + + @classmethod + def resolve_container(cls, path): + path = cls.__clean_path(path) + view, args, kwargs = get_resolver().resolve(path) + return view.initkwargs['model'] + + @classmethod + def resolve(cls, path): + container = cls.resolve_container(path) + try: + resolve_id = cls.resolve_id(path) + except: + resolve_id = None + return container, resolve_id + + @classmethod + def __clean_path(cls, path): + if not path.startswith("/"): + path = "/{}".format(path) + if not path.endswith("/"): + path = "{}/".format(path) + return path + class LDPSource(models.Model): container = models.URLField() diff --git a/djangoldp/tests/tests_ldp_model.py b/djangoldp/tests/tests_ldp_model.py index 8a17c88f..56bbe552 100644 --- a/djangoldp/tests/tests_ldp_model.py +++ b/djangoldp/tests/tests_ldp_model.py @@ -20,6 +20,14 @@ class LDPModelTest(TestCase): self.assertEquals("/ldp-dummys/", Model.container_id(dummy)) self.assertEquals("/ldp-dummys/{}".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)) + self.assertEquals(saved_instance, result) + + def test_resolve_container(self): + result = Model.resolve_container("/dummys/") + self.assertEquals(Dummy, result) @unittest.skip("futur feature: avoid urls.py on apps") def test_auto_url(self): -- GitLab From 5404fcce35a450771a0fb72014055702ace5000b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Wed, 20 Feb 2019 12:29:23 +0100 Subject: [PATCH 8/8] syntax: refactor to use Model utilities functions --- djangoldp/serializers.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py index a2d0f6dc..18a63a1d 100644 --- a/djangoldp/serializers.py +++ b/djangoldp/serializers.py @@ -16,6 +16,8 @@ from rest_framework.settings import api_settings from rest_framework.utils.field_mapping import get_nested_relation_kwargs from rest_framework.utils.serializer_helpers import ReturnDict +from djangoldp.models import Model + class LDListMixin: def to_internal_value(self, data): @@ -40,9 +42,8 @@ class LDListMixin: def get_value(self, dictionary): try: object_list = dictionary["@graph"] - view_name = '{}-list'.format(self.parent.Meta.model._meta.object_name.lower()) - part_id = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0]) - obj = next(filter(lambda o: part_id in o['@id'], object_list)) + container_id = Model.container_id(self.parent.instance) + obj = next(filter(lambda o: container_id in o['@id'], object_list)) list = super().get_value(obj) try: list = next(filter(lambda o: list['@id'] == o['@id'], object_list)) @@ -197,9 +198,8 @@ class LDPSerializer(HyperlinkedModelSerializer): def get_value(self, dictionary): try: object_list = dictionary["@graph"] - part_id = '/{}'.format(get_resolver().reverse_dict[self.parent_view_name][0][0][0], - self.parent.instance.pk) - obj = next(filter(lambda o: part_id in o['@id'], object_list)) + resource_id = Model.resource_id(self.parent.instance) + obj = next(filter(lambda o: resource_id in o['@id'], object_list)) return super().get_value(obj) except KeyError: return super().get_value(dictionary) @@ -288,10 +288,8 @@ class LDPSerializer(HyperlinkedModelSerializer): def get_value(self, dictionary): try: object_list = dictionary["@graph"] - view_name = '{}-list'.format(self.parent.Meta.model._meta.object_name.lower()) - part_id = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0], - self.parent.instance.pk) - obj = next(filter(lambda o: part_id in o[self.url_field_name], object_list)) + container_id = Model.container_path(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 if item is empty: -- GitLab