mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-03 03:43:32 +03:00
Clean up field initialization. Fixes #497
This commit is contained in:
parent
628e3bf001
commit
497da7fc69
|
@ -100,7 +100,8 @@ class BaseSerializer(Field):
|
||||||
_options_class = SerializerOptions
|
_options_class = SerializerOptions
|
||||||
_dict_class = SortedDictWithMetadata # Set to unsorted dict for backwards compatibility with unsorted implementations.
|
_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)
|
super(BaseSerializer, self).__init__(**kwargs)
|
||||||
self.opts = self._options_class(self.Meta)
|
self.opts = self._options_class(self.Meta)
|
||||||
self.parent = None
|
self.parent = None
|
||||||
|
@ -151,8 +152,6 @@ class BaseSerializer(Field):
|
||||||
base_fields = copy.deepcopy(self.base_fields)
|
base_fields = copy.deepcopy(self.base_fields)
|
||||||
for key, field in base_fields.items():
|
for key, field in base_fields.items():
|
||||||
ret[key] = field
|
ret[key] = field
|
||||||
# Set up the field
|
|
||||||
field.initialize(parent=self, field_name=key)
|
|
||||||
|
|
||||||
# Add in the default fields
|
# Add in the default fields
|
||||||
default_fields = self.get_default_fields()
|
default_fields = self.get_default_fields()
|
||||||
|
@ -172,6 +171,10 @@ class BaseSerializer(Field):
|
||||||
for key in self.opts.exclude:
|
for key in self.opts.exclude:
|
||||||
ret.pop(key, None)
|
ret.pop(key, None)
|
||||||
|
|
||||||
|
# Initialize the fields
|
||||||
|
for key, field in ret.items():
|
||||||
|
field.initialize(parent=self, field_name=key)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
#####
|
#####
|
||||||
|
@ -186,6 +189,13 @@ class BaseSerializer(Field):
|
||||||
if parent.opts.depth:
|
if parent.opts.depth:
|
||||||
self.opts.depth = parent.opts.depth - 1
|
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.
|
# Methods to convert or revert from objects <--> primitive representations.
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.test import TestCase
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.tests.models import (Album, ActionItem, Anchor, BasicModel,
|
from rest_framework.tests.models import (Album, ActionItem, Anchor, BasicModel,
|
||||||
BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel,
|
BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel,
|
||||||
ManyToManyModel, Person, ReadOnlyManyToManyModel)
|
ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo)
|
||||||
|
|
||||||
|
|
||||||
class SubComment(object):
|
class SubComment(object):
|
||||||
|
@ -764,3 +764,55 @@ class DepthTest(TestCase):
|
||||||
'writer': {'id': 1, 'name': u'django', 'age': 1}}
|
'writer': {'id': 1, 'name': u'django', 'age': 1}}
|
||||||
|
|
||||||
self.assertEqual(serializer.data, expected)
|
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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user