# """ # Tests to cover nested serializers. # Doesn't cover model serializers. # """ # from __future__ import unicode_literals # from django.test import TestCase # from rest_framework import serializers # from . import models # class WritableNestedSerializerBasicTests(TestCase): # """ # Tests for deserializing nested entities. # Basic tests that use serializers that simply restore to dicts. # """ # def setUp(self): # class TrackSerializer(serializers.Serializer): # order = serializers.IntegerField() # title = serializers.CharField(max_length=100) # duration = serializers.IntegerField() # class AlbumSerializer(serializers.Serializer): # album_name = serializers.CharField(max_length=100) # artist = serializers.CharField(max_length=100) # tracks = TrackSerializer(many=True) # self.AlbumSerializer = AlbumSerializer # def test_nested_validation_success(self): # """ # Correct nested serialization should return the input data. # """ # data = { # 'album_name': 'Discovery', # 'artist': 'Daft Punk', # 'tracks': [ # {'order': 1, 'title': 'One More Time', 'duration': 235}, # {'order': 2, 'title': 'Aerodynamic', 'duration': 184}, # {'order': 3, 'title': 'Digital Love', 'duration': 239} # ] # } # serializer = self.AlbumSerializer(data=data) # self.assertEqual(serializer.is_valid(), True) # self.assertEqual(serializer.object, data) # def test_nested_validation_error(self): # """ # Incorrect nested serialization should return appropriate error data. # """ # data = { # 'album_name': 'Discovery', # 'artist': 'Daft Punk', # 'tracks': [ # {'order': 1, 'title': 'One More Time', 'duration': 235}, # {'order': 2, 'title': 'Aerodynamic', 'duration': 184}, # {'order': 3, 'title': 'Digital Love', 'duration': 'foobar'} # ] # } # expected_errors = { # 'tracks': [ # {}, # {}, # {'duration': ['Enter a whole number.']} # ] # } # serializer = self.AlbumSerializer(data=data) # self.assertEqual(serializer.is_valid(), False) # self.assertEqual(serializer.errors, expected_errors) # def test_many_nested_validation_error(self): # """ # Incorrect nested serialization should return appropriate error data # when multiple entities are being deserialized. # """ # data = [ # { # 'album_name': 'Russian Red', # 'artist': 'I Love Your Glasses', # 'tracks': [ # {'order': 1, 'title': 'Cigarettes', 'duration': 121}, # {'order': 2, 'title': 'No Past Land', 'duration': 198}, # {'order': 3, 'title': 'They Don\'t Believe', 'duration': 191} # ] # }, # { # 'album_name': 'Discovery', # 'artist': 'Daft Punk', # 'tracks': [ # {'order': 1, 'title': 'One More Time', 'duration': 235}, # {'order': 2, 'title': 'Aerodynamic', 'duration': 184}, # {'order': 3, 'title': 'Digital Love', 'duration': 'foobar'} # ] # } # ] # expected_errors = [ # {}, # { # 'tracks': [ # {}, # {}, # {'duration': ['Enter a whole number.']} # ] # } # ] # serializer = self.AlbumSerializer(data=data, many=True) # self.assertEqual(serializer.is_valid(), False) # self.assertEqual(serializer.errors, expected_errors) # class WritableNestedSerializerObjectTests(TestCase): # """ # Tests for deserializing nested entities. # These tests use serializers that restore to concrete objects. # """ # def setUp(self): # # Couple of concrete objects that we're going to deserialize into # class Track(object): # def __init__(self, order, title, duration): # self.order, self.title, self.duration = order, title, duration # def __eq__(self, other): # return ( # self.order == other.order and # self.title == other.title and # self.duration == other.duration # ) # class Album(object): # def __init__(self, album_name, artist, tracks): # self.album_name, self.artist, self.tracks = album_name, artist, tracks # def __eq__(self, other): # return ( # self.album_name == other.album_name and # self.artist == other.artist and # self.tracks == other.tracks # ) # # And their corresponding serializers # class TrackSerializer(serializers.Serializer): # order = serializers.IntegerField() # title = serializers.CharField(max_length=100) # duration = serializers.IntegerField() # def restore_object(self, attrs, instance=None): # return Track(attrs['order'], attrs['title'], attrs['duration']) # class AlbumSerializer(serializers.Serializer): # album_name = serializers.CharField(max_length=100) # artist = serializers.CharField(max_length=100) # tracks = TrackSerializer(many=True) # def restore_object(self, attrs, instance=None): # return Album(attrs['album_name'], attrs['artist'], attrs['tracks']) # self.Album, self.Track = Album, Track # self.AlbumSerializer = AlbumSerializer # def test_nested_validation_success(self): # """ # Correct nested serialization should return a restored object # that corresponds to the input data. # """ # data = { # 'album_name': 'Discovery', # 'artist': 'Daft Punk', # 'tracks': [ # {'order': 1, 'title': 'One More Time', 'duration': 235}, # {'order': 2, 'title': 'Aerodynamic', 'duration': 184}, # {'order': 3, 'title': 'Digital Love', 'duration': 239} # ] # } # expected_object = self.Album( # album_name='Discovery', # artist='Daft Punk', # tracks=[ # self.Track(order=1, title='One More Time', duration=235), # self.Track(order=2, title='Aerodynamic', duration=184), # self.Track(order=3, title='Digital Love', duration=239), # ] # ) # serializer = self.AlbumSerializer(data=data) # self.assertEqual(serializer.is_valid(), True) # self.assertEqual(serializer.object, expected_object) # def test_many_nested_validation_success(self): # """ # Correct nested serialization should return multiple restored objects # that corresponds to the input data when multiple objects are # being deserialized. # """ # data = [ # { # 'album_name': 'Russian Red', # 'artist': 'I Love Your Glasses', # 'tracks': [ # {'order': 1, 'title': 'Cigarettes', 'duration': 121}, # {'order': 2, 'title': 'No Past Land', 'duration': 198}, # {'order': 3, 'title': 'They Don\'t Believe', 'duration': 191} # ] # }, # { # 'album_name': 'Discovery', # 'artist': 'Daft Punk', # 'tracks': [ # {'order': 1, 'title': 'One More Time', 'duration': 235}, # {'order': 2, 'title': 'Aerodynamic', 'duration': 184}, # {'order': 3, 'title': 'Digital Love', 'duration': 239} # ] # } # ] # expected_object = [ # self.Album( # album_name='Russian Red', # artist='I Love Your Glasses', # tracks=[ # self.Track(order=1, title='Cigarettes', duration=121), # self.Track(order=2, title='No Past Land', duration=198), # self.Track(order=3, title='They Don\'t Believe', duration=191), # ] # ), # self.Album( # album_name='Discovery', # artist='Daft Punk', # tracks=[ # self.Track(order=1, title='One More Time', duration=235), # self.Track(order=2, title='Aerodynamic', duration=184), # self.Track(order=3, title='Digital Love', duration=239), # ] # ) # ] # 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) # class NestedModelSerializerUpdateTests(TestCase): # def test_second_nested_level(self): # john = models.Person.objects.create(name="john") # post = john.blogpost_set.create(title="Test blog post") # post.blogpostcomment_set.create(text="I hate this blog post") # post.blogpostcomment_set.create(text="I love this blog post") # class BlogPostCommentSerializer(serializers.ModelSerializer): # class Meta: # model = models.BlogPostComment # class BlogPostSerializer(serializers.ModelSerializer): # comments = BlogPostCommentSerializer(many=True, source='blogpostcomment_set') # class Meta: # model = models.BlogPost # fields = ('id', 'title', 'comments') # class PersonSerializer(serializers.ModelSerializer): # posts = BlogPostSerializer(many=True, source='blogpost_set') # class Meta: # model = models.Person # fields = ('id', 'name', 'age', 'posts') # serialize = PersonSerializer(instance=john) # deserialize = PersonSerializer(data=serialize.data, instance=john) # self.assertTrue(deserialize.is_valid()) # result = deserialize.object # result.save() # self.assertEqual(result.id, john.id)