aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rest_framework/serializers.py16
-rw-r--r--rest_framework/tests/serializer.py54
2 files changed, 66 insertions, 4 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 5465d7b7..caa7c980 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -100,7 +100,8 @@ class BaseSerializer(Field):
_options_class = SerializerOptions
_dict_class = SortedDictWithMetadata # Set to unsorted dict for backwards compatibility with unsorted implementations.
- def __init__(self, instance=None, data=None, files=None, context=None, partial=False, **kwargs):
+ def __init__(self, instance=None, data=None, files=None,
+ context=None, partial=False, **kwargs):
super(BaseSerializer, self).__init__(**kwargs)
self.opts = self._options_class(self.Meta)
self.parent = None
@@ -151,8 +152,6 @@ class BaseSerializer(Field):
base_fields = copy.deepcopy(self.base_fields)
for key, field in base_fields.items():
ret[key] = field
- # Set up the field
- field.initialize(parent=self, field_name=key)
# Add in the default fields
default_fields = self.get_default_fields()
@@ -172,6 +171,10 @@ class BaseSerializer(Field):
for key in self.opts.exclude:
ret.pop(key, None)
+ # Initialize the fields
+ for key, field in ret.items():
+ field.initialize(parent=self, field_name=key)
+
return ret
#####
@@ -186,6 +189,13 @@ class BaseSerializer(Field):
if parent.opts.depth:
self.opts.depth = parent.opts.depth - 1
+ # We need to call initialize here to ensure any nested
+ # serializers that will have already called initialize on their
+ # descendants get updated with *their* parent.
+ # We could be a bit more smart about this, but it'll do for now.
+ for key, field in self.fields.items():
+ field.initialize(parent=self, field_name=key)
+
#####
# Methods to convert or revert from objects <--> primitive representations.
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index 50a5f5a4..780177aa 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -4,7 +4,7 @@ from django.test import TestCase
from rest_framework import serializers
from rest_framework.tests.models import (Album, ActionItem, Anchor, BasicModel,
BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel,
- ManyToManyModel, Person, ReadOnlyManyToManyModel)
+ ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo)
class SubComment(object):
@@ -764,3 +764,55 @@ class DepthTest(TestCase):
'writer': {'id': 1, 'name': u'django', 'age': 1}}
self.assertEqual(serializer.data, expected)
+
+
+class NestedSerializerContextTests(TestCase):
+
+ def test_nested_serializer_context(self):
+ """
+ Regression for #497
+
+ https://github.com/tomchristie/django-rest-framework/issues/497
+ """
+ class PhotoSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Photo
+ fields = ("description", "callable")
+
+ callable = serializers.SerializerMethodField('_callable')
+
+ def _callable(self, instance):
+ if not 'context_item' in self.context:
+ raise RuntimeError("context isn't getting passed into 2nd level nested serializer")
+ return "success"
+
+ class AlbumSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Album
+ fields = ("photo_set", "callable")
+
+ photo_set = PhotoSerializer(source="photo_set")
+ callable = serializers.SerializerMethodField("_callable")
+
+ def _callable(self, instance):
+ if not 'context_item' in self.context:
+ raise RuntimeError("context isn't getting passed into 1st level nested serializer")
+ return "success"
+
+ class AlbumCollection(object):
+ albums = None
+
+ class AlbumCollectionSerializer(serializers.Serializer):
+ albums = AlbumSerializer(source="albums")
+
+ album1 = Album.objects.create(title="album 1")
+ album2 = Album.objects.create(title="album 2")
+ Photo.objects.create(description="Bigfoot", album=album1)
+ Photo.objects.create(description="Unicorn", album=album1)
+ Photo.objects.create(description="Yeti", album=album2)
+ Photo.objects.create(description="Sasquatch", album=album2)
+ album_collection = AlbumCollection()
+ album_collection.albums = [album1, album2]
+
+ # This will raise RuntimeError if context doesn't get passed correctly to the nested Serializers
+ AlbumCollectionSerializer(album_collection, context={'context_item': 'album context'}).data