2
Tests to cover nested serializers.
4
Doesn't cover model serializers.
6
from __future__ import unicode_literals
7
from django.test import TestCase
8
from rest_framework import serializers
11
class WritableNestedSerializerBasicTests(TestCase):
13
Tests for deserializing nested entities.
14
Basic tests that use serializers that simply restore to dicts.
18
class TrackSerializer(serializers.Serializer):
19
order = serializers.IntegerField()
20
title = serializers.CharField(max_length=100)
21
duration = serializers.IntegerField()
23
class AlbumSerializer(serializers.Serializer):
24
album_name = serializers.CharField(max_length=100)
25
artist = serializers.CharField(max_length=100)
26
tracks = TrackSerializer(many=True)
28
self.AlbumSerializer = AlbumSerializer
30
def test_nested_validation_success(self):
32
Correct nested serialization should return the input data.
36
'album_name': 'Discovery',
37
'artist': 'Daft Punk',
39
{'order': 1, 'title': 'One More Time', 'duration': 235},
40
{'order': 2, 'title': 'Aerodynamic', 'duration': 184},
41
{'order': 3, 'title': 'Digital Love', 'duration': 239}
45
serializer = self.AlbumSerializer(data=data)
46
self.assertEqual(serializer.is_valid(), True)
47
self.assertEqual(serializer.object, data)
49
def test_nested_validation_error(self):
51
Incorrect nested serialization should return appropriate error data.
55
'album_name': 'Discovery',
56
'artist': 'Daft Punk',
58
{'order': 1, 'title': 'One More Time', 'duration': 235},
59
{'order': 2, 'title': 'Aerodynamic', 'duration': 184},
60
{'order': 3, 'title': 'Digital Love', 'duration': 'foobar'}
67
{'duration': ['Enter a whole number.']}
71
serializer = self.AlbumSerializer(data=data)
72
self.assertEqual(serializer.is_valid(), False)
73
self.assertEqual(serializer.errors, expected_errors)
75
def test_many_nested_validation_error(self):
77
Incorrect nested serialization should return appropriate error data
78
when multiple entities are being deserialized.
83
'album_name': 'Russian Red',
84
'artist': 'I Love Your Glasses',
86
{'order': 1, 'title': 'Cigarettes', 'duration': 121},
87
{'order': 2, 'title': 'No Past Land', 'duration': 198},
88
{'order': 3, 'title': 'They Don\'t Believe', 'duration': 191}
92
'album_name': 'Discovery',
93
'artist': 'Daft Punk',
95
{'order': 1, 'title': 'One More Time', 'duration': 235},
96
{'order': 2, 'title': 'Aerodynamic', 'duration': 184},
97
{'order': 3, 'title': 'Digital Love', 'duration': 'foobar'}
107
{'duration': ['Enter a whole number.']}
112
serializer = self.AlbumSerializer(data=data, many=True)
113
self.assertEqual(serializer.is_valid(), False)
114
self.assertEqual(serializer.errors, expected_errors)
117
class WritableNestedSerializerObjectTests(TestCase):
119
Tests for deserializing nested entities.
120
These tests use serializers that restore to concrete objects.
124
# Couple of concrete objects that we're going to deserialize into
126
def __init__(self, order, title, duration):
127
self.order, self.title, self.duration = order, title, duration
129
def __eq__(self, other):
131
self.order == other.order and
132
self.title == other.title and
133
self.duration == other.duration
137
def __init__(self, album_name, artist, tracks):
138
self.album_name, self.artist, self.tracks = album_name, artist, tracks
140
def __eq__(self, other):
142
self.album_name == other.album_name and
143
self.artist == other.artist and
144
self.tracks == other.tracks
147
# And their corresponding serializers
148
class TrackSerializer(serializers.Serializer):
149
order = serializers.IntegerField()
150
title = serializers.CharField(max_length=100)
151
duration = serializers.IntegerField()
153
def restore_object(self, attrs, instance=None):
154
return Track(attrs['order'], attrs['title'], attrs['duration'])
156
class AlbumSerializer(serializers.Serializer):
157
album_name = serializers.CharField(max_length=100)
158
artist = serializers.CharField(max_length=100)
159
tracks = TrackSerializer(many=True)
161
def restore_object(self, attrs, instance=None):
162
return Album(attrs['album_name'], attrs['artist'], attrs['tracks'])
164
self.Album, self.Track = Album, Track
165
self.AlbumSerializer = AlbumSerializer
167
def test_nested_validation_success(self):
169
Correct nested serialization should return a restored object
170
that corresponds to the input data.
174
'album_name': 'Discovery',
175
'artist': 'Daft Punk',
177
{'order': 1, 'title': 'One More Time', 'duration': 235},
178
{'order': 2, 'title': 'Aerodynamic', 'duration': 184},
179
{'order': 3, 'title': 'Digital Love', 'duration': 239}
182
expected_object = self.Album(
183
album_name='Discovery',
186
self.Track(order=1, title='One More Time', duration=235),
187
self.Track(order=2, title='Aerodynamic', duration=184),
188
self.Track(order=3, title='Digital Love', duration=239),
192
serializer = self.AlbumSerializer(data=data)
193
self.assertEqual(serializer.is_valid(), True)
194
self.assertEqual(serializer.object, expected_object)
196
def test_many_nested_validation_success(self):
198
Correct nested serialization should return multiple restored objects
199
that corresponds to the input data when multiple objects are
205
'album_name': 'Russian Red',
206
'artist': 'I Love Your Glasses',
208
{'order': 1, 'title': 'Cigarettes', 'duration': 121},
209
{'order': 2, 'title': 'No Past Land', 'duration': 198},
210
{'order': 3, 'title': 'They Don\'t Believe', 'duration': 191}
214
'album_name': 'Discovery',
215
'artist': 'Daft Punk',
217
{'order': 1, 'title': 'One More Time', 'duration': 235},
218
{'order': 2, 'title': 'Aerodynamic', 'duration': 184},
219
{'order': 3, 'title': 'Digital Love', 'duration': 239}
225
album_name='Russian Red',
226
artist='I Love Your Glasses',
228
self.Track(order=1, title='Cigarettes', duration=121),
229
self.Track(order=2, title='No Past Land', duration=198),
230
self.Track(order=3, title='They Don\'t Believe', duration=191),
234
album_name='Discovery',
237
self.Track(order=1, title='One More Time', duration=235),
238
self.Track(order=2, title='Aerodynamic', duration=184),
239
self.Track(order=3, title='Digital Love', duration=239),
244
serializer = self.AlbumSerializer(data=data, many=True)
245
self.assertEqual(serializer.is_valid(), True)
246
self.assertEqual(serializer.object, expected_object)
249
class ForeignKeyNestedSerializerUpdateTests(TestCase):
251
class Artist(object):
252
def __init__(self, name):
255
def __eq__(self, other):
256
return self.name == other.name
259
def __init__(self, name, artist):
260
self.name, self.artist = name, artist
262
def __eq__(self, other):
263
return self.name == other.name and self.artist == other.artist
265
class ArtistSerializer(serializers.Serializer):
266
name = serializers.CharField()
268
def restore_object(self, attrs, instance=None):
270
instance.name = attrs['name']
272
instance = Artist(attrs['name'])
275
class AlbumSerializer(serializers.Serializer):
276
name = serializers.CharField()
277
by = ArtistSerializer(source='artist')
279
def restore_object(self, attrs, instance=None):
281
instance.name = attrs['name']
282
instance.artist = attrs['artist']
284
instance = Album(attrs['name'], attrs['artist'])
289
self.AlbumSerializer = AlbumSerializer
291
def test_create_via_foreign_key_with_source(self):
293
Check that we can both *create* and *update* into objects across
294
ForeignKeys that have a `source` specified.
295
Regression test for #1170
299
'by': {'name': 'Daft Punk'},
302
expected = self.Album(artist=self.Artist('Daft Punk'), name='Discovery')
305
serializer = self.AlbumSerializer(data=data)
306
self.assertEqual(serializer.is_valid(), True)
307
self.assertEqual(serializer.object, expected)
310
original = self.Album(artist=self.Artist('The Bats'), name='Free All the Monsters')
311
serializer = self.AlbumSerializer(instance=original, data=data)
312
self.assertEqual(serializer.is_valid(), True)
313
self.assertEqual(serializer.object, expected)