Commit 9c944971 authored by Jean-Baptiste's avatar Jean-Baptiste

Merge branch '168-put-m2m' into 'master'

Resolve "Issue with ManyToManyField while PUTting resource"

Closes #168

See merge request !93
parents ce1b7789 16e5df94
Pipeline #5198 passed with stage
in 1 minute and 21 seconds
...@@ -2,6 +2,7 @@ from django.contrib.auth.models import User ...@@ -2,6 +2,7 @@ from django.contrib.auth.models import User
from django.db import models from django.db import models
from django.db.models.base import ModelBase from django.db.models.base import ModelBase
from django.urls import get_resolver from django.urls import get_resolver
from django.utils.datastructures import MultiValueDict, MultiValueDictKeyError
from django.utils.decorators import classonlymethod from django.utils.decorators import classonlymethod
from djangoldp.permissions import LDPPermissions from djangoldp.permissions import LDPPermissions
...@@ -53,7 +54,10 @@ class Model(models.Model): ...@@ -53,7 +54,10 @@ class Model(models.Model):
else: else:
object_name = instance_or_model._meta.object_name.lower() object_name = instance_or_model._meta.object_name.lower()
view_name = '{}-detail'.format(object_name) 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('/'): if slug_field.startswith('/'):
slug_field = slug_field[1:] slug_field = slug_field[1:]
return slug_field return slug_field
......
...@@ -567,7 +567,7 @@ class LDPSerializer(HyperlinkedModelSerializer): ...@@ -567,7 +567,7 @@ class LDPSerializer(HyperlinkedModelSerializer):
def save_or_update_nested_list(self, instance, nested_fields): def save_or_update_nested_list(self, instance, nested_fields):
for (field_name, data) in nested_fields: for (field_name, data) in nested_fields:
manager = getattr(instance, field_name) manager = getattr(instance, field_name)
slug_field = Model.slug_field(instance) slug_field = Model.slug_field(manager.model)
try: try:
item_pk_to_keep = list(map(lambda e: e[slug_field], filter(lambda x: slug_field in x, data))) item_pk_to_keep = list(map(lambda e: e[slug_field], filter(lambda x: slug_field in x, data)))
except TypeError: except TypeError:
...@@ -587,8 +587,11 @@ class LDPSerializer(HyperlinkedModelSerializer): ...@@ -587,8 +587,11 @@ class LDPSerializer(HyperlinkedModelSerializer):
saved_item = item saved_item = item
elif slug_field in item: elif slug_field in item:
kwargs = {slug_field: item[slug_field]} kwargs = {slug_field: item[slug_field]}
old_obj = manager.model.objects.get(**kwargs) try:
saved_item = self.update(instance=old_obj, validated_data=item) 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: else:
rel = getattr(instance._meta.model, field_name).rel rel = getattr(instance._meta.model, field_name).rel
try: try:
......
...@@ -65,6 +65,7 @@ class Resource(Model): ...@@ -65,6 +65,7 @@ class Resource(Model):
owner_perms = ['inherit'] owner_perms = ['inherit']
serializer_fields = ["@id", "joboffers"] serializer_fields = ["@id", "joboffers"]
nested_fields = ["joboffers"] nested_fields = ["joboffers"]
depth = 1
class UserProfile(Model): class UserProfile(Model):
......
...@@ -71,7 +71,7 @@ failures = test_runner.run_tests([ ...@@ -71,7 +71,7 @@ failures = test_runner.run_tests([
'djangoldp.tests.tests_delete', 'djangoldp.tests.tests_delete',
'djangoldp.tests.tests_sources', 'djangoldp.tests.tests_sources',
'djangoldp.tests.tests_pagination', 'djangoldp.tests.tests_pagination',
# 'djangoldp.tests.tests_temp' 'djangoldp.tests.tests_temp'
]) ])
if failures: if failures:
......
import json
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.test import TestCase from django.test import TestCase
from rest_framework.test import APIRequestFactory, APIClient from rest_framework.test import APIRequestFactory, APIClient
from djangoldp.tests.models import Resource, JobOffer
class TestTemp(TestCase): class TestTemp(TestCase):
...@@ -12,3 +16,4 @@ class TestTemp(TestCase): ...@@ -12,3 +16,4 @@ class TestTemp(TestCase):
def tearDown(self): def tearDown(self):
pass pass
...@@ -4,7 +4,7 @@ from rest_framework.test import APIRequestFactory, APIClient ...@@ -4,7 +4,7 @@ from rest_framework.test import APIRequestFactory, APIClient
from rest_framework.utils import json from rest_framework.utils import json
from djangoldp.serializers import LDPSerializer 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 from djangoldp.tests.models import Skill, JobOffer, Conversation, Message
...@@ -395,3 +395,85 @@ class Update(TestCase): ...@@ -395,3 +395,85 @@ class Update(TestCase):
content_type='application/ld+json') content_type='application/ld+json')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['peer_user'], None) 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 = {
'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")
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")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment