aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2013-10-17 07:59:29 -0700
committerTom Christie2013-10-17 07:59:29 -0700
commit2394f05e5a0a566366b066081002bfcf9a290589 (patch)
tree6e7f0ab3cbc7417bfe719c752e5724008d189475
parent6a40202a644055808bde355471b1400264d0dada (diff)
parent86ea969e1154de20a53fc5b853e8340508648e98 (diff)
downloaddjango-rest-framework-2394f05e5a0a566366b066081002bfcf9a290589.tar.bz2
Merge pull request #1170 from craigds/write-into-foreignkey-with-source
fix writing into foreign key with non-null source
-rw-r--r--rest_framework/serializers.py2
-rw-r--r--rest_framework/tests/test_serializer_nested.py67
2 files changed, 68 insertions, 1 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 05c9eb47..4210d058 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -406,7 +406,7 @@ class BaseSerializer(WritableField):
return
# Set the serializer object if it exists
- obj = getattr(self.parent.object, field_name) if self.parent.object else None
+ obj = get_component(self.parent.object, self.source or field_name) if self.parent.object else None
obj = obj.all() if is_simple_callable(getattr(obj, 'all', None)) else obj
if self.source == '*':
diff --git a/rest_framework/tests/test_serializer_nested.py b/rest_framework/tests/test_serializer_nested.py
index 71d0e24b..029f8bff 100644
--- a/rest_framework/tests/test_serializer_nested.py
+++ b/rest_framework/tests/test_serializer_nested.py
@@ -244,3 +244,70 @@ class WritableNestedSerializerObjectTests(TestCase):
serializer = self.AlbumSerializer(data=data, many=True)
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(serializer.object, expected_object)
+
+
+class ForeignKeyNestedSerializerUpdateTests(TestCase):
+ def setUp(self):
+ class Artist(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ class Album(object):
+ def __init__(self, name, artist):
+ self.name, self.artist = name, artist
+
+ def __eq__(self, other):
+ return self.name == other.name and self.artist == other.artist
+
+ class ArtistSerializer(serializers.Serializer):
+ name = serializers.CharField()
+
+ def restore_object(self, attrs, instance=None):
+ if instance:
+ instance.name = attrs['name']
+ else:
+ instance = Artist(attrs['name'])
+ return instance
+
+ class AlbumSerializer(serializers.Serializer):
+ name = serializers.CharField()
+ by = ArtistSerializer(source='artist')
+
+ def restore_object(self, attrs, instance=None):
+ if instance:
+ instance.name = attrs['name']
+ instance.artist = attrs['artist']
+ else:
+ instance = Album(attrs['name'], attrs['artist'])
+ return instance
+
+ self.Artist = Artist
+ self.Album = Album
+ self.AlbumSerializer = AlbumSerializer
+
+ def test_create_via_foreign_key_with_source(self):
+ """
+ Check that we can both *create* and *update* into objects across
+ ForeignKeys that have a `source` specified.
+ Regression test for #1170
+ """
+ data = {
+ 'name': 'Discovery',
+ 'by': {'name': 'Daft Punk'},
+ }
+
+ expected = self.Album(artist=self.Artist('Daft Punk'), name='Discovery')
+
+ # create
+ serializer = self.AlbumSerializer(data=data)
+ self.assertEqual(serializer.is_valid(), True)
+ self.assertEqual(serializer.object, expected)
+
+ # update
+ original = self.Album(artist=self.Artist('The Bats'), name='Free All the Monsters')
+ serializer = self.AlbumSerializer(instance=original, data=data)
+ self.assertEqual(serializer.is_valid(), True)
+ self.assertEqual(serializer.object, expected)