From abe655e061871a568cccf473414e350f3eb61d8b Mon Sep 17 00:00:00 2001 From: Yuri Prezument Date: Mon, 12 Aug 2013 21:01:37 +0300 Subject: [PATCH 1/3] Make OneToOneSource.target nullable --- rest_framework/tests/test_relations_nested.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rest_framework/tests/test_relations_nested.py b/rest_framework/tests/test_relations_nested.py index 8325580f6..30229687c 100644 --- a/rest_framework/tests/test_relations_nested.py +++ b/rest_framework/tests/test_relations_nested.py @@ -10,7 +10,8 @@ class OneToOneTarget(models.Model): class OneToOneSource(models.Model): name = models.CharField(max_length=100) - target = models.OneToOneField(OneToOneTarget, related_name='source') + target = models.OneToOneField(OneToOneTarget, related_name='source', + null=True, blank=True) class OneToManyTarget(models.Model): @@ -21,7 +22,7 @@ class OneToManySource(models.Model): name = models.CharField(max_length=100) target = models.ForeignKey(OneToManyTarget, related_name='sources') - + class ReverseNestedOneToOneTests(TestCase): def setUp(self): class OneToOneSourceSerializer(serializers.ModelSerializer): From 901d2b0eb8270befa051510e190f3d5679086c7f Mon Sep 17 00:00:00 2001 From: Yuri Prezument Date: Mon, 12 Aug 2013 21:02:59 +0300 Subject: [PATCH 2/3] Failing test case for nullifying nested object --- rest_framework/tests/test_relations_nested.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/rest_framework/tests/test_relations_nested.py b/rest_framework/tests/test_relations_nested.py index 30229687c..d393b0c35 100644 --- a/rest_framework/tests/test_relations_nested.py +++ b/rest_framework/tests/test_relations_nested.py @@ -180,6 +180,25 @@ class ForwardNestedOneToOneTests(TestCase): ] self.assertEqual(serializer.data, expected) + def test_one_to_one_update_to_null(self): + data = {'id': 3, 'name': 'source-3-updated', 'target': None} + instance = OneToOneSource.objects.get(pk=3) + serializer = self.Serializer(instance, data=data) + self.assertTrue(serializer.is_valid()) + obj = serializer.save() + + self.assertEqual(serializer.data, data) + self.assertEqual(obj.name, 'source-3-updated') + self.assertEqual(obj.target, None) + + queryset = OneToOneSource.objects.all() + serializer = self.Serializer(queryset, many=True) + expected = [ + {'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}}, + {'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}}, + {'id': 3, 'name': 'source-3-updated', 'target': None} + ] + self.assertEqual(serializer.data, expected) # TODO: Nullable 1-1 tests # def test_one_to_one_delete(self): From ff1efcf60f0a9b66cdb736f8c0b2cfe2fc84cdf5 Mon Sep 17 00:00:00 2001 From: Yuri Prezument Date: Mon, 12 Aug 2013 18:08:23 +0300 Subject: [PATCH 3/3] If null or blank - don't save the nested object --- rest_framework/serializers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index d8f9145ec..2b260c256 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -522,7 +522,7 @@ class BaseSerializer(WritableField): if self.object._deleted: [self.delete_object(item) for item in self.object._deleted] else: - self.save_object(self.object, **kwargs) + self.save_object(self.object, **kwargs) return self.object @@ -891,7 +891,8 @@ class ModelSerializer(Serializer): # Nested relationships need to be saved before we can save the # parent instance. for field_name, sub_object in obj._nested_forward_relations.items(): - self.save_object(sub_object) + if sub_object: + self.save_object(sub_object) setattr(obj, field_name, sub_object) obj.save(**kwargs)