From f8b9306e76f35610228e9c47707a809a68ec8b5f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Mon, 2 Sep 2019 12:57:40 +0200 Subject: [PATCH 1/2] update: add failing tests --- djangoldp/tests/models.py | 1 + djangoldp/tests/runner.py | 22 ++++++------ djangoldp/tests/tests_temp.py | 62 +++++++++++++++++++++++++++++++++ djangoldp/tests/tests_update.py | 20 ++++++++++- 4 files changed, 93 insertions(+), 12 deletions(-) diff --git a/djangoldp/tests/models.py b/djangoldp/tests/models.py index 332cc391..fe6de31f 100644 --- a/djangoldp/tests/models.py +++ b/djangoldp/tests/models.py @@ -65,6 +65,7 @@ class Resource(Model): owner_perms = ['inherit'] serializer_fields = ["@id", "joboffers"] nested_fields = ["joboffers"] + depth = 1 class UserProfile(Model): diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py index 2dd377fa..57001ea8 100644 --- a/djangoldp/tests/runner.py +++ b/djangoldp/tests/runner.py @@ -61,17 +61,17 @@ from django.test.runner import DiscoverRunner test_runner = DiscoverRunner(verbosity=1) failures = test_runner.run_tests([ - 'djangoldp.tests.tests_ldp_model', - 'djangoldp.tests.tests_save', - 'djangoldp.tests.tests_user_permissions', - 'djangoldp.tests.tests_anonymous_permissions', - 'djangoldp.tests.tests_update', - 'djangoldp.tests.tests_auto_author', - 'djangoldp.tests.tests_get', - 'djangoldp.tests.tests_delete', - 'djangoldp.tests.tests_sources', - 'djangoldp.tests.tests_pagination', - # 'djangoldp.tests.tests_temp' + # 'djangoldp.tests.tests_ldp_model', + # 'djangoldp.tests.tests_save', + # 'djangoldp.tests.tests_user_permissions', + # 'djangoldp.tests.tests_anonymous_permissions', + # 'djangoldp.tests.tests_update', + # 'djangoldp.tests.tests_auto_author', + # 'djangoldp.tests.tests_get', + # 'djangoldp.tests.tests_delete', + # 'djangoldp.tests.tests_sources', + # 'djangoldp.tests.tests_pagination', + 'djangoldp.tests.tests_temp' ]) if failures: diff --git a/djangoldp/tests/tests_temp.py b/djangoldp/tests/tests_temp.py index 6896080d..104dea95 100644 --- a/djangoldp/tests/tests_temp.py +++ b/djangoldp/tests/tests_temp.py @@ -1,7 +1,11 @@ +import json + 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, JobOffer + class TestTemp(TestCase): @@ -12,3 +16,61 @@ class TestTemp(TestCase): def tearDown(self): pass + + # def test_m2m_existing_link(self): + # resource = Resource.objects.create() + # job = JobOffer.objects.create(title="first title", slug="job") + # resource.joboffers.add(job) + # resource.save() + # body = { + # 'http://happy-dev.fr/owl/#joboffers': { + # '@id': '/job-offers/{}'.format(job.slug), + # 'http://happy-dev.fr/owl/#title': "new job", + # } + # } + # + # 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://testserver/job-offers/aaa/") + # self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "new job") + + def test_m2m_new_link(self): + resource = Resource.objects.create() + job = JobOffer.objects.create(title="first title", slug="job") + body = { + 'http://happy-dev.fr/owl/#joboffers': { + '@id': 'http://testserver/job-offers/{}/'.format(job.slug), + } + } + + 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://testserver/job-offers/{}/".format(job.slug)) + self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "job") + + def test_m2m_new_link_bis(self): + resource = Resource.objects.create() + job = JobOffer.objects.create(title="first title", slug="job") + body = { + 'http://happy-dev.fr/owl/#joboffers': + { + '@id': "http://testserver/resources/{}/joboffers/".format(resource.pk), + "ldp:contains": [ + {'@id': 'http://testserver/job-offers/{}/'.format(job.slug)}, + ] + } + } + + 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://testserver/job-offers/{}/".format(job.slug)) + self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "job") diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py index 292b0baf..f9cab272 100644 --- a/djangoldp/tests/tests_update.py +++ b/djangoldp/tests/tests_update.py @@ -4,7 +4,7 @@ from rest_framework.test import APIRequestFactory, APIClient from rest_framework.utils import json from djangoldp.serializers import LDPSerializer -from djangoldp.tests.models import Post, UserProfile +from djangoldp.tests.models import Post, UserProfile, Resource from djangoldp.tests.models import Skill, JobOffer, Conversation, Message @@ -395,3 +395,21 @@ class Update(TestCase): content_type='application/ld+json') self.assertEqual(response.status_code, 200) self.assertEqual(response.data['peer_user'], None) + + def test_m2m_new_link_embedded(self): + resource = Resource.objects.create() + body = { + 'http://happy-dev.fr/owl/#joboffers': { + 'http://happy-dev.fr/owl/#slug': 'aaa', + 'http://happy-dev.fr/owl/#title': "new job", + } + } + + 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://testserver/job-offers/aaa/") + self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "new job") + -- GitLab From 16e5df94d14aa4c02f5e89f4ae46e4f7459253a6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste <bleme@pm.me> Date: Mon, 2 Sep 2019 14:50:59 +0200 Subject: [PATCH 2/2] update: fix PUT on m2M relations --- djangoldp/models.py | 6 +++- djangoldp/serializers.py | 9 +++-- djangoldp/tests/runner.py | 20 +++++------ djangoldp/tests/tests_temp.py | 57 ----------------------------- djangoldp/tests/tests_update.py | 64 +++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 71 deletions(-) diff --git a/djangoldp/models.py b/djangoldp/models.py index 7507c0bf..778c5e7d 100644 --- a/djangoldp/models.py +++ b/djangoldp/models.py @@ -2,6 +2,7 @@ from django.contrib.auth.models import User from django.db import models from django.db.models.base import ModelBase from django.urls import get_resolver +from django.utils.datastructures import MultiValueDict, MultiValueDictKeyError from django.utils.decorators import classonlymethod from djangoldp.permissions import LDPPermissions @@ -53,7 +54,10 @@ class Model(models.Model): else: object_name = instance_or_model._meta.object_name.lower() view_name = '{}-detail'.format(object_name) - slug_field = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][1][0]) + 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') if slug_field.startswith('/'): slug_field = slug_field[1:] return slug_field diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py index ba22a039..4a3990f3 100644 --- a/djangoldp/serializers.py +++ b/djangoldp/serializers.py @@ -567,7 +567,7 @@ 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) + slug_field = Model.slug_field(manager.model) try: item_pk_to_keep = list(map(lambda e: e[slug_field], filter(lambda x: slug_field in x, data))) except TypeError: @@ -587,8 +587,11 @@ class LDPSerializer(HyperlinkedModelSerializer): saved_item = item elif slug_field in item: kwargs = {slug_field: item[slug_field]} - old_obj = manager.model.objects.get(**kwargs) - saved_item = self.update(instance=old_obj, validated_data=item) + try: + old_obj = manager.model.objects.get(**kwargs) + saved_item = self.update(instance=old_obj, validated_data=item) + except manager.model.DoesNotExist: + saved_item = self.internal_create(validated_data=item, model=manager.model) else: rel = getattr(instance._meta.model, field_name).rel try: diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py index 57001ea8..6a4195f8 100644 --- a/djangoldp/tests/runner.py +++ b/djangoldp/tests/runner.py @@ -61,16 +61,16 @@ from django.test.runner import DiscoverRunner test_runner = DiscoverRunner(verbosity=1) failures = test_runner.run_tests([ - # 'djangoldp.tests.tests_ldp_model', - # 'djangoldp.tests.tests_save', - # 'djangoldp.tests.tests_user_permissions', - # 'djangoldp.tests.tests_anonymous_permissions', - # 'djangoldp.tests.tests_update', - # 'djangoldp.tests.tests_auto_author', - # 'djangoldp.tests.tests_get', - # 'djangoldp.tests.tests_delete', - # 'djangoldp.tests.tests_sources', - # 'djangoldp.tests.tests_pagination', + 'djangoldp.tests.tests_ldp_model', + 'djangoldp.tests.tests_save', + 'djangoldp.tests.tests_user_permissions', + 'djangoldp.tests.tests_anonymous_permissions', + 'djangoldp.tests.tests_update', + 'djangoldp.tests.tests_auto_author', + 'djangoldp.tests.tests_get', + 'djangoldp.tests.tests_delete', + 'djangoldp.tests.tests_sources', + 'djangoldp.tests.tests_pagination', 'djangoldp.tests.tests_temp' ]) diff --git a/djangoldp/tests/tests_temp.py b/djangoldp/tests/tests_temp.py index 104dea95..21c77f6c 100644 --- a/djangoldp/tests/tests_temp.py +++ b/djangoldp/tests/tests_temp.py @@ -17,60 +17,3 @@ class TestTemp(TestCase): def tearDown(self): pass - # def test_m2m_existing_link(self): - # resource = Resource.objects.create() - # job = JobOffer.objects.create(title="first title", slug="job") - # resource.joboffers.add(job) - # resource.save() - # body = { - # 'http://happy-dev.fr/owl/#joboffers': { - # '@id': '/job-offers/{}'.format(job.slug), - # 'http://happy-dev.fr/owl/#title': "new job", - # } - # } - # - # 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://testserver/job-offers/aaa/") - # self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "new job") - - def test_m2m_new_link(self): - resource = Resource.objects.create() - job = JobOffer.objects.create(title="first title", slug="job") - body = { - 'http://happy-dev.fr/owl/#joboffers': { - '@id': 'http://testserver/job-offers/{}/'.format(job.slug), - } - } - - 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://testserver/job-offers/{}/".format(job.slug)) - self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "job") - - def test_m2m_new_link_bis(self): - resource = Resource.objects.create() - job = JobOffer.objects.create(title="first title", slug="job") - body = { - 'http://happy-dev.fr/owl/#joboffers': - { - '@id': "http://testserver/resources/{}/joboffers/".format(resource.pk), - "ldp:contains": [ - {'@id': 'http://testserver/job-offers/{}/'.format(job.slug)}, - ] - } - } - - 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://testserver/job-offers/{}/".format(job.slug)) - self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "job") diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py index f9cab272..431db723 100644 --- a/djangoldp/tests/tests_update.py +++ b/djangoldp/tests/tests_update.py @@ -396,6 +396,46 @@ class Update(TestCase): self.assertEqual(response.status_code, 200) self.assertEqual(response.data['peer_user'], None) + def test_m2m_new_link(self): + resource = Resource.objects.create() + job = JobOffer.objects.create(title="first title", slug="job") + body = { + 'http://happy-dev.fr/owl/#joboffers': { + '@id': 'http://testserver/job-offers/{}/'.format(job.slug), + } + } + + 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://testserver/job-offers/{}/".format(job.slug)) + self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "first title") + + def test_m2m_new_link_bis(self): + resource = Resource.objects.create() + job = JobOffer.objects.create(title="first title", slug="job") + body = { + 'http://happy-dev.fr/owl/#joboffers': + { + '@id': "http://testserver/resources/{}/joboffers/".format(resource.pk), + 'ldp:contains': [ + {'@id': 'http://testserver/job-offers/{}/'.format(job.slug), + 'http://happy-dev.fr/owl/#title': "new job", + }, + ] + } + } + + 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://testserver/job-offers/{}/".format(job.slug)) + self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "new job") + def test_m2m_new_link_embedded(self): resource = Resource.objects.create() body = { @@ -413,3 +453,27 @@ class Update(TestCase): "http://testserver/job-offers/aaa/") self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "new job") + def test_m2m_existing_link(self): + resource = Resource.objects.create() + job = JobOffer.objects.create(title="first title", slug="job") + resource.joboffers.add(job) + resource.save() + body = { + 'http://happy-dev.fr/owl/#joboffers': { + # '@id': "http://testserver/resources/{}/joboffers/".format(resource.pk), + 'ldp:contains': [ + { + '@id': 'http://testserver/job-offers/{}/'.format(job.slug), + 'http://happy-dev.fr/owl/#title': "new job", + } + ] + } + } + + 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://testserver/job-offers/{}/".format(job.slug)) + self.assertEqual(response.data['joboffers']['ldp:contains'][0]['title'], "new job") -- GitLab