diff --git a/djangoldp/migrations/0003_auto_20190911_0931.py b/djangoldp/migrations/0003_auto_20190911_0931.py new file mode 100644 index 0000000000000000000000000000000000000000..72aa15bfbea5ed5f146cec65899bd9632fc47dcb --- /dev/null +++ b/djangoldp/migrations/0003_auto_20190911_0931.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2019-09-11 09:31 +from __future__ import unicode_literals + +from django.db import migrations +import djangoldp.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangoldp', '0002_auto_20190906_0642'), + ] + + operations = [ + migrations.AlterField( + model_name='ldpsource', + name='urlid', + field=djangoldp.fields.LDPUrlField(blank=True, null=True, unique=True), + ), + ] diff --git a/djangoldp/models.py b/djangoldp/models.py index 3dce34ef3348e1373dd90905fdf09217ba72fa0e..c9f545dca94268162909bd98c87a30370f805f95 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -2,8 +2,10 @@ from django.conf import settings from django.contrib.auth.models import User from django.db import models from django.db.models.base import ModelBase +from django.db.models.signals import pre_save, post_save +from django.dispatch import receiver from django.urls import get_resolver -from django.utils.datastructures import MultiValueDict, MultiValueDictKeyError +from django.utils.datastructures import MultiValueDictKeyError from django.utils.decorators import classonlymethod from djangoldp.fields import LDPUrlField @@ -14,7 +16,10 @@ User._meta.owner_field = "id" class Model(models.Model): - urlid = LDPUrlField(null=True, unique=True) + urlid = LDPUrlField(blank=True, null=True, unique=True) + + def __init__(self, *args, **kwargs): + super(Model, self).__init__(*args, **kwargs) @classmethod def get_view_set(cls): @@ -33,7 +38,10 @@ class Model(models.Model): return cls.__clean_path(path) def get_absolute_url(self): - return Model.resource_id(self) + if self.urlid is None or self.urlid != '': + return '{}{}'.format(settings.BASE_URL, Model.resource_id(self)) + else: + return self.urlid def get_container_id(self): return Model.container_id(self) @@ -57,7 +65,7 @@ class Model(models.Model): else: object_name = instance_or_model._meta.object_name.lower() view_name = '{}-detail'.format(object_name) - try : + try: slug_field = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][1][0]) except MultiValueDictKeyError: slug_field = Model.get_meta(instance_or_model, 'lookup_field', 'pk') @@ -159,3 +167,11 @@ class LDPSource(Model): def __str__(self): return "{}: {}".format(self.federation, self.urlid) + + +@receiver([post_save]) +def auto_urlid(sender, instance, **kwargs): + if isinstance(instance, Model) and (instance.urlid is None or instance.urlid == ''): + instance.urlid = instance.get_absolute_url() + instance.save() + diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py index c3bf10a6c537097ab4bd6106577277962f36366b..8d6757635a775089c867996cbc851f8e441bdbef 100644 --- a/djangoldp/tests/models.py +++ b/djangoldp/tests/models.py @@ -24,7 +24,7 @@ class Skill(Model): class JobOffer(Model): - title = models.CharField(max_length=255, blank=True, null=True) + title = models.CharField(max_length=255, null=True) skills = models.ManyToManyField(Skill, blank=True) slug = models.SlugField(blank=True, null=True, unique=True) date = models.DateTimeField(auto_now_add=True, blank=True) @@ -58,6 +58,7 @@ class Conversation(models.Model): class Resource(Model): joboffers = models.ManyToManyField(JobOffer, blank=True, related_name='resources') + description = models.CharField(max_length=255) class Meta: anonymous_perms = ['view', 'add', 'delete', 'add', 'change', 'control'] diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py index 9b83a4fc2f7eaa059ada26a6689aceb6e95d284e..f0fb6b439daeedd5d4d86ef00f815fa6138324a8 100644 --- a/djangoldp/tests/runner.py +++ b/djangoldp/tests/runner.py @@ -49,7 +49,8 @@ settings.configure(DEBUG=False, 'djangoldp.tests', ), SITE_URL='http://happy-dev.fr', - REST_FRAMEWORK={ + BASE_URL='http://happy-dev.fr', + REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'djangoldp.pagination.LDPPagination', 'PAGE_SIZE': 5 }, @@ -71,7 +72,7 @@ failures = test_runner.run_tests([ 'djangoldp.tests.tests_delete', 'djangoldp.tests.tests_sources', 'djangoldp.tests.tests_pagination', - 'djangoldp.tests.tests_temp' + # 'djangoldp.tests.tests_temp' ]) if failures: diff --git a/djangoldp/tests/tests_ldp_model.py b/djangoldp/tests/tests_ldp_model.py index 14217f94a0dc1985f0ee4ea8d71f64a43caa51e7..bc316ed50914dea6fb6fc99847392fa9d09e2562 100644 --- a/djangoldp/tests/tests_ldp_model.py +++ b/djangoldp/tests/tests_ldp_model.py @@ -16,7 +16,7 @@ class LDPModelTest(TestCase): def test_class_inheriting_ldp_model(self): dummy = LDPDummy.objects.create(some="text") self.assertEquals("/ldpdummys/", dummy.get_container_id()) - self.assertEquals("/ldpdummys/{}/".format(dummy.pk), dummy.get_absolute_url()) + self.assertEquals("http://happy-dev.fr/ldpdummys/{}/".format(dummy.pk), dummy.get_absolute_url()) self.assertEquals("/ldpdummys/", Model.container_id(dummy)) self.assertEquals("/ldpdummys/{}/".format(dummy.pk), Model.resource_id(dummy)) @@ -33,6 +33,6 @@ class LDPModelTest(TestCase): 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 = 'http://happy-dev.fr/{}{}/'.format(get_resolver().reverse_dict[view_name][0][0][0], dummy.pk) self.assertEquals(path, dummy.get_absolute_url()) diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py index 089cb551050e55d9341e7afa801388fcaf5bff76..8885ecb3b1c563a07bd302923887582794c54154 100644 --- a/djangoldp/tests/tests_save.py +++ b/djangoldp/tests/tests_save.py @@ -3,7 +3,7 @@ from rest_framework.utils import json from djangoldp.models import Model from djangoldp.serializers import LDPSerializer -from djangoldp.tests.models import Skill, JobOffer, Invoice, LDPDummy, Resource +from djangoldp.tests.models import Skill, JobOffer, Invoice, LDPDummy, Resource, Post class Save(TestCase): @@ -88,8 +88,8 @@ class Save(TestCase): self.assertIs(result.skills.count(), 0) def test_save_m2m_graph_with_nested(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="a") + skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire", slug="b") job = {"@graph": [ {"title": "job test", @@ -111,9 +111,9 @@ class Save(TestCase): self.assertEquals(result.skills.all()[0].title, "skill3 NEW") # creation on the fly def test_save_without_nested_fields(self): - skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire") - skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire") - job = {"title": "job test"} + skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire", slug="a") + skill2 = Skill.objects.create(title="skill2", obligatoire="obligatoire", slug="b") + job = {"title": "job test", "slug": "c"} meta_args = {'model': JobOffer, 'depth': 2, 'fields': ("@id", "title", "skills")} @@ -265,7 +265,8 @@ class Save(TestCase): data=json.dumps(body), content_type='application/ld+json') self.assertEqual(response.status_code, 201) - self.assertEqual(response.data['resources']['ldp:contains'][0]['@id'], "http://testserver/resources/{}/".format(resource.pk)) + self.assertEqual(response.data['resources']['ldp:contains'][0]['@id'], + "http://testserver/resources/{}/".format(resource.pk)) self.assertEqual(response.data['title'], "new job") def test_nested_container_federated(self): @@ -278,7 +279,8 @@ class Save(TestCase): data=json.dumps(body), content_type='application/ld+json') self.assertEqual(response.status_code, 201) - self.assertEqual(response.data['resources']['ldp:contains'][0]['@id'], "http://testserver/resources/{}/".format(resource.pk)) + self.assertEqual(response.data['resources']['ldp:contains'][0]['@id'], + "http://testserver/resources/{}/".format(resource.pk)) self.assertEqual(response.data['@id'], "http://external.job/job/1") def test_embedded_context_2(self): @@ -294,3 +296,35 @@ class Save(TestCase): response = self.client.post('/posts/', data=json.dumps(body), content_type='application/ld+json') self.assertEqual(response.status_code, 201) + + def test_auto_id(self): + body = { + '@id': "./", + 'content': "post update", + 'peer_user': "", + '@context': { + "@vocab": "http://happy-dev.fr/owl/#", + } + } + + response = self.client.post('/posts/', data=json.dumps(body), + content_type='application/ld+json') + self.assertEqual(response.status_code, 201) + saved_post = Post.objects.get(pk=1) + self.assertEqual(saved_post.urlid, "https://happy-dev.fr/posts/1/") + + def test_auto_id(self): + body = { + '@id': "./", + 'content': "post update", + 'peer_user': "", + '@context': { + "@vocab": "http://happy-dev.fr/owl/#", + } + } + + response = self.client.post('/posts/', data=json.dumps(body), + content_type='application/ld+json') + self.assertEqual(response.status_code, 201) + saved_post = Post.objects.get(pk=1) + self.assertEqual(saved_post.urlid, "http://happy-dev.fr/posts/1/") diff --git a/djangoldp/tests/tests_temp.py b/djangoldp/tests/tests_temp.py index b3ef7100cea8141b870c33296df8616979c57f10..eaef247795d1c2842633147f9a346149df3a459f 100644 --- a/djangoldp/tests/tests_temp.py +++ b/djangoldp/tests/tests_temp.py @@ -2,6 +2,8 @@ from django.contrib.auth.models import User from django.test import TestCase from rest_framework.test import APIRequestFactory, APIClient +from djangoldp.tests.models import Resource + class TestTemp(TestCase): @@ -13,3 +15,31 @@ class TestTemp(TestCase): def tearDown(self): pass + def test_nested_container_federated(self): + resource = Resource.objects.create() + body = { + 'http://happy-dev.fr/owl/#@id': "http://external.job/job/1", + } + + response = self.client.post('/resources/{}/joboffers/'.format(resource.pk), + data=json.dumps(body), + content_type='application/ld+json') + self.assertEqual(response.status_code, 201) + self.assertEqual(response.data['resources']['ldp:contains'][0]['@id'], "http://testserver/resources/{}/".format(resource.pk)) + self.assertEqual(response.data['@id'], "http://external.job/job/1") + + def test_m2m_new_link_federated(self): + resource = Resource.objects.create() + body = { + 'http://happy-dev.fr/owl/#joboffers': { + 'http://happy-dev.fr/owl/#@id': 'http://external.job/job/1', + } + } + + response = self.client.put('/resources/{}/'.format(resource.pk), + data=json.dumps(body), + content_type='application/ld+json') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data['joboffers']['ldp:contains'][0]['@id'], + "http://external.job/job/1") + diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py index bbd9846ac2767bd8484a5a19e3dd83a1c8fe83a6..7db97dee730dc73f4dbdaffc8b7546cbdbb3a167 100644 --- a/djangoldp/tests/tests_update.py +++ b/djangoldp/tests/tests_update.py @@ -450,7 +450,7 @@ class Update(TestCase): content_type='application/ld+json') self.assertEqual(response.status_code, 200) self.assertEqual(response.data['joboffers']['ldp:contains'][0]['@id'], - "http://testserver/job-offers/aaa/") + "http://happy-dev.fr/job-offers/aaa/") self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "new job") def test_m2m_existing_link(self):