diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py index 54c599c6d75699f867d665cc1018bab89fc12e3d..9bb033b6e5090df3df30cd53b5af654239cc7feb 100644 --- a/djangoldp/serializers.py +++ b/djangoldp/serializers.py @@ -13,6 +13,7 @@ from rest_framework.fields import get_error_detail, set_value from rest_framework.relations import HyperlinkedRelatedField, ManyRelatedField, MANY_RELATION_KWARGS from rest_framework.serializers import HyperlinkedModelSerializer, ListSerializer from rest_framework.settings import api_settings +from rest_framework.utils import model_meta from rest_framework.utils.field_mapping import get_nested_relation_kwargs from rest_framework.utils.serializer_helpers import ReturnDict @@ -309,7 +310,23 @@ class LDPSerializer(HyperlinkedModelSerializer): return super().get_value(dictionary) def create(self, validated_data): - return self.internal_create(validated_data, model=self.Meta.model) + instance = self.internal_create(validated_data, model=self.Meta.model) + + self.attach_related_object(instance, validated_data) + + return instance + + def attach_related_object(self, instance, validated_data): + ModelClass = self.Meta.model + + info = model_meta.get_field_info(ModelClass) + many_to_many = {} + for field_name, relation_info in info.relations.items(): + if relation_info.to_many and relation_info.reverse and not (field_name in validated_data): + rel = getattr(instance._meta.model, field_name).rel + if rel.name in validated_data: + related = validated_data[rel.name] + getattr(instance, field_name).add(related) def internal_create(self, validated_data, model): nested_fields = [] diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py index 7e05496ab21ab8aff4e639bd6d80dcc5c8873ae5..4cf4f0d48b0079bb07a30fd14d24448619b62071 100644 --- a/djangoldp/tests/tests_save.py +++ b/djangoldp/tests/tests_save.py @@ -15,6 +15,7 @@ class Save(TestCase): "ldp:contains": [ {"@id": "https://happy-dev.fr/skills/{}/".format(skill1.pk)}, {"@id": "https://happy-dev.fr/skills/{}/".format(skill2.pk), "title": "skill2 UP"}, + {"title": "skill3 NEW", "obligatoire":"obligatoire"}, ]} } @@ -27,9 +28,10 @@ class Save(TestCase): result = serializer.save() self.assertEquals(result.title, "job test") - self.assertIs(result.skills.count(), 2) + self.assertIs(result.skills.count(), 3) self.assertEquals(result.skills.all()[0].title, "skill1") # no change self.assertEquals(result.skills.all()[1].title, "skill2 UP") # title updated + self.assertEquals(result.skills.all()[2].title, "skill3 NEW") # creation on the fly def test_save_without_nested_fields(self): skill1 = Skill.objects.create(title="skill1", obligatoire="obligatoire") @@ -47,3 +49,25 @@ class Save(TestCase): self.assertEquals(result.title, "job test") self.assertIs(result.skills.count(), 0) + def test_save_on_sub_iri(self): + """ + POST /job-offers/1/skills/ + """ + job = JobOffer.objects.create(title="job test") + skill = {"title": "new SKILL"} + + meta_args = {'model': Skill, 'depth': 1, 'fields': ("@id", "title")} + + meta_class = type('Meta', (), meta_args) + serializer_class = type(LDPSerializer)('SkillSerializer', (LDPSerializer,), {'Meta': meta_class}) + serializer = serializer_class(data=skill) + serializer.is_valid() + kwargs = {} + kwargs['joboffer'] = job + result = serializer.save(**kwargs) + + self.assertEquals(result.title, "new SKILL") + self.assertIs(result.joboffer_set.count(), 1) + self.assertEquals(result.joboffer_set.get(), job) + self.assertIs(result.joboffer_set.get().skills.count(), 1) +