This commit is contained in:
Mark Shirley 2013-03-23 09:04:55 -07:00
commit ea5d49bbd5
2 changed files with 108 additions and 5 deletions

View File

@ -386,12 +386,15 @@ class BaseSerializer(WritableField):
'data': value,
'context': self.context,
'partial': self.partial,
'many': self.many
'many': self.many,
'allow_delete': self.allow_delete
}
serializer = self.__class__(**kwargs)
serializer.root = self.root
if serializer.is_valid():
into[self.source or field_name] = serializer.object
self.root._deleted = (self.root._deleted or []) + (serializer._deleted or [])
else:
# Propagate errors up to our parent
raise NestedValidationError(serializer.errors)
@ -452,7 +455,7 @@ class BaseSerializer(WritableField):
ret.append(self.from_native(item, None))
errors.append(self._errors)
if update:
if update and self.allow_delete:
self._deleted = identity_to_objects.values()
self._errors = any(errors) and errors or []
@ -508,7 +511,7 @@ class BaseSerializer(WritableField):
else:
self.save_object(self.object, **kwargs)
if self.allow_delete and self._deleted:
if self._deleted:
[self.delete_object(item) for item in self._deleted]
return self.object

View File

@ -138,12 +138,46 @@ class BulkUpdateSerializerTests(TestCase):
self.title = title
self.author = author
@property
def pages(self):
return [item for item in Page.object_map.values() if item.book_id == self.id]
def save(self):
Book.object_map[self.id] = self
def delete(self):
del Book.object_map[self.id]
class Page(object):
"""
A data type that can be persisted to a mock storage backend
with `.save()` and `.delete()`.
"""
object_map = {}
def __init__(self, id, number, book_id):
self.id = id
self.number = number
self.book_id = book_id
def save(self):
Page.object_map[self.id] = self
def delete(self):
del Page.object_map[self.id]
class PageSerializer(serializers.Serializer):
id = serializers.IntegerField()
number = serializers.IntegerField()
book_id = serializers.IntegerField()
def restore_object(self, attrs, instance=None):
if instance:
instance.id = attrs['id']
instance.number = attrs['number']
return instance
return Page(**attrs)
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=100)
@ -157,8 +191,22 @@ class BulkUpdateSerializerTests(TestCase):
return instance
return Book(**attrs)
self.Book = Book
self.BookSerializer = BookSerializer
class BookNestedSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=100)
author = serializers.CharField(max_length=100)
pages = PageSerializer(many=True, allow_delete=True)
def restore_object(self, attrs, instance=None):
if instance:
instance.id = attrs['id']
instance.title = attrs['title']
instance.author = attrs['author']
return instance
return Book(**attrs)
self.Book, self.Page = Book, Page
self.BookSerializer, self.BookNestedSerializer = BookSerializer, BookNestedSerializer
data = [
{
@ -180,6 +228,29 @@ class BulkUpdateSerializerTests(TestCase):
book = Book(item['id'], item['title'], item['author'])
book.save()
data = [
{
'id': 0,
'number': 1,
'book_id': 0
},
{
'id': 1,
'number': 2,
'book_id': 0
},
{
'id': 2,
'number': 3,
'book_id': 0
}
]
for item in data:
page = Page(item['id'], item['number'], item['book_id'])
page.save()
def books(self):
"""
Return all the objects in the mock storage backend.
@ -208,6 +279,35 @@ class BulkUpdateSerializerTests(TestCase):
new_data = self.BookSerializer(self.books(), many=True).data
self.assertEqual(data, new_data)
def test_nested_bulk_update_success(self):
"""
Correct bulk update serialization should return the input data.
"""
data = {
'id': 0,
'title': 'The electric kool-aid acid test',
'author': 'Tom Wolfe',
'pages': [
{
'id': 0,
'number': 1,
'book_id': 0
},
{
'id': 2,
'number': 3,
'book_id': 0
}
]
}
book = self.Book.object_map[0]
serializer = self.BookNestedSerializer(book, data=data)
self.assertEqual(serializer.is_valid(), True)
serializer.save()
book = self.Book.object_map[0]
new_data = self.BookNestedSerializer(book).data
self.assertEqual(data, new_data)
def test_bulk_update_and_create(self):
"""
Bulk update serialization may also include created items.