Commit b7b942c5 by Tom Christie

Swap position of `instance` and `data` keyword arguments.

parent 5b397e50
...@@ -57,9 +57,16 @@ To run the tests. ...@@ -57,9 +57,16 @@ To run the tests.
# Changelog # Changelog
## Master ## 2.1.0
* Minor field improvements (don't stringify dicts, more robust many-pk fields) **Date**: 5th Nov 2012
**Warning**: Please read [this thread][2.1.0-notes] regarding the `instance` and `data` keyword args before updating to 2.1.0.
* **Serializer `instance` and `data` keyword args have their position swapped.**
* Support Django's cache framework.
* Minor field improvements. (Don't stringify dicts, more robust many-pk fields.)
* Bugfixes (Support choice field in Browseable API)
## 2.0.2 ## 2.0.2
...@@ -113,6 +120,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -113,6 +120,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[0.4]: https://github.com/tomchristie/django-rest-framework/tree/0.4.X [0.4]: https://github.com/tomchristie/django-rest-framework/tree/0.4.X
[sandbox]: http://restframework.herokuapp.com/ [sandbox]: http://restframework.herokuapp.com/
[rest-framework-2-announcement]: topics/rest-framework-2-announcement.md [rest-framework-2-announcement]: topics/rest-framework-2-announcement.md
[2.1.0-notes]: https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion
[docs]: http://django-rest-framework.org/ [docs]: http://django-rest-framework.org/
[urlobject]: https://github.com/zacharyvoase/urlobject [urlobject]: https://github.com/zacharyvoase/urlobject
......
...@@ -47,7 +47,7 @@ The first part of serializer class defines the fields that get serialized/deseri ...@@ -47,7 +47,7 @@ The first part of serializer class defines the fields that get serialized/deseri
We can now use `CommentSerializer` to serialize a comment, or list of comments. Again, using the `Serializer` class looks a lot like using a `Form` class. We can now use `CommentSerializer` to serialize a comment, or list of comments. Again, using the `Serializer` class looks a lot like using a `Form` class.
serializer = CommentSerializer(instance=comment) serializer = CommentSerializer(comment)
serializer.data serializer.data
# {'email': u'leila@example.com', 'content': u'foo bar', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774)} # {'email': u'leila@example.com', 'content': u'foo bar', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774)}
...@@ -65,20 +65,29 @@ Deserialization is similar. First we parse a stream into python native datatype ...@@ -65,20 +65,29 @@ Deserialization is similar. First we parse a stream into python native datatype
...then we restore those native datatypes into a fully populated object instance. ...then we restore those native datatypes into a fully populated object instance.
serializer = CommentSerializer(data) serializer = CommentSerializer(data=data)
serializer.is_valid() serializer.is_valid()
# True # True
serializer.object serializer.object
# <Comment object at 0x10633b2d0> # <Comment object at 0x10633b2d0>
>>> serializer.deserialize('json', stream) >>> serializer.deserialize('json', stream)
When deserializing data, we can either create a new instance, or update an existing instance.
serializer = CommentSerializer(data=data) # Create new instance
serializer = CommentSerializer(comment, data=data) # Update `instance`
## Validation ## Validation
When deserializing data, you always need to call `is_valid()` before attempting to access the deserialized object. If any validation errors occur, the `.errors` and `.non_field_errors` properties will contain the resulting error messages. When deserializing data, you always need to call `is_valid()` before attempting to access the deserialized object. If any validation errors occur, the `.errors` and `.non_field_errors` properties will contain the resulting error messages.
### Field-level validation ### Field-level validation
You can specify custom field-level validation by adding `validate_<fieldname>()` methods to your `Serializer` subclass. These are analagous to `clean_<fieldname>` methods on Django forms, but accept slightly different arguments. They take a dictionary of deserialized attributes as a first argument, and the field name in that dictionary as a second argument (which will be either the name of the field or the value of the `source` argument to the field, if one was provided). Your `validate_<fieldname>` methods should either just return the attrs dictionary or raise a `ValidationError`. For example: You can specify custom field-level validation by adding `.validate_<fieldname>` methods to your `Serializer` subclass. These are analagous to `.clean_<fieldname>` methods on Django forms, but accept slightly different arguments.
They take a dictionary of deserialized attributes as a first argument, and the field name in that dictionary as a second argument (which will be either the name of the field or the value of the `source` argument to the field, if one was provided).
Your `validate_<fieldname>` methods should either just return the `attrs` dictionary or raise a `ValidationError`. For example:
from rest_framework import serializers from rest_framework import serializers
...@@ -88,16 +97,22 @@ You can specify custom field-level validation by adding `validate_<fieldname>()` ...@@ -88,16 +97,22 @@ You can specify custom field-level validation by adding `validate_<fieldname>()`
def validate_title(self, attrs, source): def validate_title(self, attrs, source):
""" """
Check that the blog post is about Django Check that the blog post is about Django.
""" """
value = attrs[source] value = attrs[source]
if "Django" not in value: if "django" not in value.lower():
raise serializers.ValidationError("Blog post is not about Django") raise serializers.ValidationError("Blog post is not about Django")
return attrs return attrs
### Final cross-field validation ### Object-level validation
To do any other validation that requires access to multiple fields, add a method called `.validate()` to your `Serializer` subclass. This method takes a single argument, which is the `attrs` dictionary. It should raise a `ValidationError` if necessary, or just return `attrs`.
## Saving object state
Serializers also include a `.save()` method that you can override if you want to provide a method of persisting the state of a deserialized object. The default behavior of the method is to simply call `.save()` on the deserialized object instance.
To do any other validation that requires access to multiple fields, add a method called `validate` to your `Serializer` subclass. This method takes a single argument, which is the `attrs` dictionary. It should raise a `ValidationError` if necessary, or just return `attrs`. The generic views provided by REST framework call the `.save()` method when updating or creating entities.
## Dealing with nested objects ## Dealing with nested objects
......
...@@ -4,8 +4,13 @@ ...@@ -4,8 +4,13 @@
> >
> &mdash; Eric S. Raymond, [The Cathedral and the Bazaar][cite]. > &mdash; Eric S. Raymond, [The Cathedral and the Bazaar][cite].
## Master ## 2.1.0
**Date**: 5th Nov 2012
**Warning**: Please read [this thread][2.1.0-notes] regarding the `instance` and `data` keyword args before updating to 2.1.0.
* **Serializer `instance` and `data` keyword args have their position swapped.**
* Support Django's cache framework. * Support Django's cache framework.
* Minor field improvements. (Don't stringify dicts, more robust many-pk fields.) * Minor field improvements. (Don't stringify dicts, more robust many-pk fields.)
* Bugfixes (Support choice field in Browseable API) * Bugfixes (Support choice field in Browseable API)
...@@ -29,7 +34,7 @@ ...@@ -29,7 +34,7 @@
**Date**: 30th Oct 2012 **Date**: 30th Oct 2012
* **Fix all of the things.** (Well, almost.) * **Fix all of the things.** (Well, almost.)
* For more information please see the [2.0 migration guide][migration]. * For more information please see the [2.0 announcement][announcement].
--- ---
...@@ -135,4 +140,5 @@ ...@@ -135,4 +140,5 @@
* Initial release. * Initial release.
[cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html [cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html
[migration]: migration.md [2.1.0-notes]: https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion
\ No newline at end of file [announcement]: rest-framework-2-announcement.md
\ No newline at end of file
...@@ -162,7 +162,7 @@ Okay, once we've got a few imports out of the way, let's create a code snippet t ...@@ -162,7 +162,7 @@ Okay, once we've got a few imports out of the way, let's create a code snippet t
We've now got a few snippet instances to play with. Let's take a look at serializing one of those instances. We've now got a few snippet instances to play with. Let's take a look at serializing one of those instances.
serializer = SnippetSerializer(instance=snippet) serializer = SnippetSerializer(snippet)
serializer.data serializer.data
# {'pk': 1, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'} # {'pk': 1, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
...@@ -181,7 +181,7 @@ Deserialization is similar. First we parse a stream into python native datatype ...@@ -181,7 +181,7 @@ Deserialization is similar. First we parse a stream into python native datatype
...then we restore those native datatypes into to a fully populated object instance. ...then we restore those native datatypes into to a fully populated object instance.
serializer = SnippetSerializer(data) serializer = SnippetSerializer(data=data)
serializer.is_valid() serializer.is_valid()
# True # True
serializer.object serializer.object
...@@ -240,12 +240,12 @@ The root of our API is going to be a view that supports listing all the existing ...@@ -240,12 +240,12 @@ The root of our API is going to be a view that supports listing all the existing
""" """
if request.method == 'GET': if request.method == 'GET':
snippets = Snippet.objects.all() snippets = Snippet.objects.all()
serializer = SnippetSerializer(instance=snippets) serializer = SnippetSerializer(snippets)
return JSONResponse(serializer.data) return JSONResponse(serializer.data)
elif request.method == 'POST': elif request.method == 'POST':
data = JSONParser().parse(request) data = JSONParser().parse(request)
serializer = SnippetSerializer(data) serializer = SnippetSerializer(data=data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return JSONResponse(serializer.data, status=201) return JSONResponse(serializer.data, status=201)
...@@ -267,12 +267,12 @@ We'll also need a view which corresponds to an individual snippet, and can be us ...@@ -267,12 +267,12 @@ We'll also need a view which corresponds to an individual snippet, and can be us
return HttpResponse(status=404) return HttpResponse(status=404)
if request.method == 'GET': if request.method == 'GET':
serializer = SnippetSerializer(instance=snippet) serializer = SnippetSerializer(snippet)
return JSONResponse(serializer.data) return JSONResponse(serializer.data)
elif request.method == 'PUT': elif request.method == 'PUT':
data = JSONParser().parse(request) data = JSONParser().parse(request)
serializer = SnippetSerializer(data, instance=snippet) serializer = SnippetSerializer(snippet, data=data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return JSONResponse(serializer.data) return JSONResponse(serializer.data)
......
...@@ -52,11 +52,11 @@ We don't need our `JSONResponse` class anymore, so go ahead and delete that. On ...@@ -52,11 +52,11 @@ We don't need our `JSONResponse` class anymore, so go ahead and delete that. On
""" """
if request.method == 'GET': if request.method == 'GET':
snippets = Snippet.objects.all() snippets = Snippet.objects.all()
serializer = SnippetSerializer(instance=snippets) serializer = SnippetSerializer(snippets)
return Response(serializer.data) return Response(serializer.data)
elif request.method == 'POST': elif request.method == 'POST':
serializer = SnippetSerializer(request.DATA) serializer = SnippetSerializer(data=request.DATA)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
...@@ -77,11 +77,11 @@ Our instance view is an improvement over the previous example. It's a little mo ...@@ -77,11 +77,11 @@ Our instance view is an improvement over the previous example. It's a little mo
return Response(status=status.HTTP_404_NOT_FOUND) return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET': if request.method == 'GET':
serializer = SnippetSerializer(instance=snippet) serializer = SnippetSerializer(snippet)
return Response(serializer.data) return Response(serializer.data)
elif request.method == 'PUT': elif request.method == 'PUT':
serializer = SnippetSerializer(request.DATA, instance=snippet) serializer = SnippetSerializer(snippet, data=request.DATA)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data) return Response(serializer.data)
......
...@@ -20,11 +20,11 @@ We'll start by rewriting the root view as a class based view. All this involves ...@@ -20,11 +20,11 @@ We'll start by rewriting the root view as a class based view. All this involves
""" """
def get(self, request, format=None): def get(self, request, format=None):
snippets = Snippet.objects.all() snippets = Snippet.objects.all()
serializer = SnippetSerializer(instance=snippets) serializer = SnippetSerializer(snippets)
return Response(serializer.data) return Response(serializer.data)
def post(self, request, format=None): def post(self, request, format=None):
serializer = SnippetSerializer(request.DATA) serializer = SnippetSerializer(data=request.DATA)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
...@@ -44,12 +44,12 @@ So far, so good. It looks pretty similar to the previous case, but we've got be ...@@ -44,12 +44,12 @@ So far, so good. It looks pretty similar to the previous case, but we've got be
def get(self, request, pk, format=None): def get(self, request, pk, format=None):
snippet = self.get_object(pk) snippet = self.get_object(pk)
serializer = SnippetSerializer(instance=snippet) serializer = SnippetSerializer(snippet)
return Response(serializer.data) return Response(serializer.data)
def put(self, request, pk, format=None): def put(self, request, pk, format=None):
snippet = self.get_object(pk) snippet = self.get_object(pk)
serializer = SnippetSerializer(request.DATA, instance=snippet) serializer = SnippetSerializer(snippet, data=request.DATA)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data) return Response(serializer.data)
......
...@@ -167,7 +167,7 @@ We've reached the end of our tutorial. If you want to get more involved in the ...@@ -167,7 +167,7 @@ We've reached the end of our tutorial. If you want to get more involved in the
* Join the [REST framework discussion group][group], and help build the community. * Join the [REST framework discussion group][group], and help build the community.
* Follow the author [on Twitter][twitter] and say hi. * Follow the author [on Twitter][twitter] and say hi.
**Now go build some awesome things.** **Now go build awesome things.**
[repo]: https://github.com/tomchristie/rest-framework-tutorial [repo]: https://github.com/tomchristie/rest-framework-tutorial
[sandbox]: http://restframework.herokuapp.com/ [sandbox]: http://restframework.herokuapp.com/
......
...@@ -48,7 +48,7 @@ class GenericAPIView(views.APIView): ...@@ -48,7 +48,7 @@ class GenericAPIView(views.APIView):
# TODO: add support for seperate serializer/deserializer # TODO: add support for seperate serializer/deserializer
serializer_class = self.get_serializer_class() serializer_class = self.get_serializer_class()
context = self.get_serializer_context() context = self.get_serializer_context()
return serializer_class(data, instance=instance, context=context) return serializer_class(instance, data=data, context=context)
class MultipleObjectAPIView(MultipleObjectMixin, GenericAPIView): class MultipleObjectAPIView(MultipleObjectMixin, GenericAPIView):
......
...@@ -82,7 +82,7 @@ class BaseSerializer(Field): ...@@ -82,7 +82,7 @@ class BaseSerializer(Field):
_options_class = SerializerOptions _options_class = SerializerOptions
_dict_class = SortedDictWithMetadata # Set to unsorted dict for backwards compatability with unsorted implementations. _dict_class = SortedDictWithMetadata # Set to unsorted dict for backwards compatability with unsorted implementations.
def __init__(self, data=None, instance=None, context=None, **kwargs): def __init__(self, instance=None, data=None, context=None, **kwargs):
super(BaseSerializer, self).__init__(**kwargs) super(BaseSerializer, self).__init__(**kwargs)
self.fields = copy.deepcopy(self.base_fields) self.fields = copy.deepcopy(self.base_fields)
self.opts = self._options_class(self.Meta) self.opts = self._options_class(self.Meta)
......
...@@ -25,7 +25,7 @@ class TestGenericRelations(TestCase): ...@@ -25,7 +25,7 @@ class TestGenericRelations(TestCase):
model = Bookmark model = Bookmark
exclude = ('id',) exclude = ('id',)
serializer = BookmarkSerializer(instance=self.bookmark) serializer = BookmarkSerializer(self.bookmark)
expected = { expected = {
'tags': [u'django', u'python'], 'tags': [u'django', u'python'],
'url': u'https://www.djangoproject.com/' 'url': u'https://www.djangoproject.com/'
......
...@@ -74,13 +74,13 @@ class UnitTestPagination(TestCase): ...@@ -74,13 +74,13 @@ class UnitTestPagination(TestCase):
self.last_page = paginator.page(3) self.last_page = paginator.page(3)
def test_native_pagination(self): def test_native_pagination(self):
serializer = pagination.PaginationSerializer(instance=self.first_page) serializer = pagination.PaginationSerializer(self.first_page)
self.assertEquals(serializer.data['count'], 26) self.assertEquals(serializer.data['count'], 26)
self.assertEquals(serializer.data['next'], '?page=2') self.assertEquals(serializer.data['next'], '?page=2')
self.assertEquals(serializer.data['previous'], None) self.assertEquals(serializer.data['previous'], None)
self.assertEquals(serializer.data['results'], self.objects[:10]) self.assertEquals(serializer.data['results'], self.objects[:10])
serializer = pagination.PaginationSerializer(instance=self.last_page) serializer = pagination.PaginationSerializer(self.last_page)
self.assertEquals(serializer.data['count'], 26) self.assertEquals(serializer.data['count'], 26)
self.assertEquals(serializer.data['next'], None) self.assertEquals(serializer.data['next'], None)
self.assertEquals(serializer.data['previous'], '?page=2') self.assertEquals(serializer.data['previous'], '?page=2')
......
...@@ -63,7 +63,7 @@ class PrimaryKeyManyToManyTests(TestCase): ...@@ -63,7 +63,7 @@ class PrimaryKeyManyToManyTests(TestCase):
def test_many_to_many_retrieve(self): def test_many_to_many_retrieve(self):
queryset = ManyToManySource.objects.all() queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(instance=queryset) serializer = ManyToManySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'targets': [1]}, {'id': 1, 'name': u'source-1', 'targets': [1]},
{'id': 2, 'name': u'source-2', 'targets': [1, 2]}, {'id': 2, 'name': u'source-2', 'targets': [1, 2]},
...@@ -73,7 +73,7 @@ class PrimaryKeyManyToManyTests(TestCase): ...@@ -73,7 +73,7 @@ class PrimaryKeyManyToManyTests(TestCase):
def test_reverse_many_to_many_retrieve(self): def test_reverse_many_to_many_retrieve(self):
queryset = ManyToManyTarget.objects.all() queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(instance=queryset) serializer = ManyToManyTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]}, {'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]},
{'id': 2, 'name': u'target-2', 'sources': [2, 3]}, {'id': 2, 'name': u'target-2', 'sources': [2, 3]},
...@@ -84,14 +84,14 @@ class PrimaryKeyManyToManyTests(TestCase): ...@@ -84,14 +84,14 @@ class PrimaryKeyManyToManyTests(TestCase):
def test_many_to_many_update(self): def test_many_to_many_update(self):
data = {'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]} data = {'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]}
instance = ManyToManySource.objects.get(pk=1) instance = ManyToManySource.objects.get(pk=1)
serializer = ManyToManySourceSerializer(data, instance=instance) serializer = ManyToManySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
self.assertEquals(serializer.data, data) self.assertEquals(serializer.data, data)
serializer.save() serializer.save()
# Ensure source 1 is updated, and everything else is as expected # Ensure source 1 is updated, and everything else is as expected
queryset = ManyToManySource.objects.all() queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(instance=queryset) serializer = ManyToManySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]}, {'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]},
{'id': 2, 'name': u'source-2', 'targets': [1, 2]}, {'id': 2, 'name': u'source-2', 'targets': [1, 2]},
...@@ -102,14 +102,14 @@ class PrimaryKeyManyToManyTests(TestCase): ...@@ -102,14 +102,14 @@ class PrimaryKeyManyToManyTests(TestCase):
def test_reverse_many_to_many_update(self): def test_reverse_many_to_many_update(self):
data = {'id': 1, 'name': u'target-1', 'sources': [1]} data = {'id': 1, 'name': u'target-1', 'sources': [1]}
instance = ManyToManyTarget.objects.get(pk=1) instance = ManyToManyTarget.objects.get(pk=1)
serializer = ManyToManyTargetSerializer(data, instance=instance) serializer = ManyToManyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
self.assertEquals(serializer.data, data) self.assertEquals(serializer.data, data)
serializer.save() serializer.save()
# Ensure target 1 is updated, and everything else is as expected # Ensure target 1 is updated, and everything else is as expected
queryset = ManyToManyTarget.objects.all() queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(instance=queryset) serializer = ManyToManyTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'sources': [1]}, {'id': 1, 'name': u'target-1', 'sources': [1]},
{'id': 2, 'name': u'target-2', 'sources': [2, 3]}, {'id': 2, 'name': u'target-2', 'sources': [2, 3]},
...@@ -130,7 +130,7 @@ class PrimaryKeyForeignKeyTests(TestCase): ...@@ -130,7 +130,7 @@ class PrimaryKeyForeignKeyTests(TestCase):
def test_foreign_key_retrieve(self): def test_foreign_key_retrieve(self):
queryset = ForeignKeySource.objects.all() queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(instance=queryset) serializer = ForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 1}, {'id': 1, 'name': u'source-1', 'target': 1},
{'id': 2, 'name': u'source-2', 'target': 1}, {'id': 2, 'name': u'source-2', 'target': 1},
...@@ -140,7 +140,7 @@ class PrimaryKeyForeignKeyTests(TestCase): ...@@ -140,7 +140,7 @@ class PrimaryKeyForeignKeyTests(TestCase):
def test_reverse_foreign_key_retrieve(self): def test_reverse_foreign_key_retrieve(self):
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(instance=queryset) serializer = ForeignKeyTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]}, {'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]},
{'id': 2, 'name': u'target-2', 'sources': []}, {'id': 2, 'name': u'target-2', 'sources': []},
...@@ -150,14 +150,14 @@ class PrimaryKeyForeignKeyTests(TestCase): ...@@ -150,14 +150,14 @@ class PrimaryKeyForeignKeyTests(TestCase):
def test_foreign_key_update(self): def test_foreign_key_update(self):
data = {'id': 1, 'name': u'source-1', 'target': 2} data = {'id': 1, 'name': u'source-1', 'target': 2}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(data, instance=instance) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
self.assertEquals(serializer.data, data) self.assertEquals(serializer.data, data)
serializer.save() serializer.save()
# # Ensure source 1 is updated, and everything else is as expected # # Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all() queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(instance=queryset) serializer = ForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 2}, {'id': 1, 'name': u'source-1', 'target': 2},
{'id': 2, 'name': u'source-2', 'target': 1}, {'id': 2, 'name': u'source-2', 'target': 1},
...@@ -172,14 +172,14 @@ class PrimaryKeyForeignKeyTests(TestCase): ...@@ -172,14 +172,14 @@ class PrimaryKeyForeignKeyTests(TestCase):
# def test_reverse_foreign_key_update(self): # def test_reverse_foreign_key_update(self):
# data = {'id': 1, 'name': u'target-1', 'sources': [1]} # data = {'id': 1, 'name': u'target-1', 'sources': [1]}
# instance = ForeignKeyTarget.objects.get(pk=1) # instance = ForeignKeyTarget.objects.get(pk=1)
# serializer = ForeignKeyTargetSerializer(data, instance=instance) # serializer = ForeignKeyTargetSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid()) # self.assertTrue(serializer.is_valid())
# self.assertEquals(serializer.data, data) # self.assertEquals(serializer.data, data)
# serializer.save() # serializer.save()
# # Ensure target 1 is updated, and everything else is as expected # # Ensure target 1 is updated, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all() # queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(instance=queryset) # serializer = ForeignKeyTargetSerializer(queryset)
# expected = [ # expected = [
# {'id': 1, 'name': u'target-1', 'sources': [1]}, # {'id': 1, 'name': u'target-1', 'sources': [1]},
# {'id': 2, 'name': u'target-2', 'sources': []}, # {'id': 2, 'name': u'target-2', 'sources': []},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment