diff --git a/djangorestframework/resources.py b/djangorestframework/resources.py index 5e350268b..09f1fa382 100644 --- a/djangorestframework/resources.py +++ b/djangorestframework/resources.py @@ -15,7 +15,7 @@ class BaseResource(Serializer): exclude = None def __init__(self, view=None, depth=None, stack=[], **kwargs): - super(BaseResource, self).__init__(depth, stack, **kwargs) + super(BaseResource, self).__init__(depth, stack, view=view, **kwargs) self.view = view self.request = getattr(view, 'request', None) @@ -33,6 +33,16 @@ class BaseResource(Serializer): """ return self.serialize(obj) + def serialize(self, obj, request=None, **kwargs): + """ + Convert the resource into a serializable representation. + """ + # Request from related serializer. + if request is not None: + self.request = request + + return super(BaseResource, self).serialize(obj, request=request, **kwargs) + class Resource(BaseResource): """ diff --git a/djangorestframework/serializer.py b/djangorestframework/serializer.py index 3f05903b5..6dd22790d 100644 --- a/djangorestframework/serializer.py +++ b/djangorestframework/serializer.py @@ -96,7 +96,7 @@ class Serializer(object): """ The maximum depth to serialize to, or `None`. """ - + parent = None """ A reference to the root serializer when descending down into fields. @@ -106,6 +106,7 @@ class Serializer(object): if depth is not None: self.depth = depth self.stack = stack + self.kwargs = kwargs def get_fields(self, obj): fields = self.fields @@ -169,7 +170,7 @@ class Serializer(object): """ return self.rename.get(smart_str(key), smart_str(key)) - def serialize_val(self, key, obj, related_info): + def serialize_val(self, key, obj, related_info, **kwargs): """ Convert a model field or dict value into a serializable representation. """ @@ -188,8 +189,8 @@ class Serializer(object): stack = self.stack[:] stack.append(obj) - return related_serializer(depth=depth, stack=stack).serialize( - obj, request=getattr(self, 'request', None)) + return related_serializer(depth=depth, stack=stack, + **self.kwargs).serialize(obj, **kwargs) def serialize_max_depth(self, obj): """ @@ -205,7 +206,7 @@ class Serializer(object): """ raise _SkipField - def serialize_model(self, instance): + def serialize_model(self, instance, **kwargs): """ Given a model instance or dict, serialize it to a dict.. """ @@ -232,7 +233,7 @@ class Serializer(object): continue key = self.serialize_key(fname) - val = self.serialize_val(fname, obj, related_info) + val = self.serialize_val(fname, obj, related_info, **kwargs) data[key] = val except _SkipField: pass @@ -263,18 +264,14 @@ class Serializer(object): """ return smart_unicode(obj, strings_only=True) - def serialize(self, obj, request=None): + def serialize(self, obj, **kwargs): """ Convert any object into a serializable representation. """ - # Request from related serializer. - if request is not None: - self.request = request - if isinstance(obj, (dict, models.Model)): # Model instances & dictionaries - return self.serialize_model(obj) + return self.serialize_model(obj, **kwargs) elif isinstance(obj, (tuple, list, set, QuerySet, RawQuerySet, types.GeneratorType)): # basic iterables return self.serialize_iter(obj) diff --git a/djangorestframework/tests/serializer.py b/djangorestframework/tests/serializer.py index 1a4eaa105..f32a79dac 100644 --- a/djangorestframework/tests/serializer.py +++ b/djangorestframework/tests/serializer.py @@ -3,6 +3,7 @@ from django.db import models from django.test import TestCase from django.utils.translation import ugettext_lazy from djangorestframework.serializer import Serializer +from djangorestframework.resources import Resource import datetime import decimal @@ -144,6 +145,31 @@ class TestFieldNesting(TestCase): self.assertEqual(SerializerM2().serialize(self.m2), {'field': {'field1': u'foo'}}) self.assertEqual(SerializerM3().serialize(self.m3), {'field': {'field2': u'bar'}}) + def test_serializer_nesting_inherits_kwargs(self): + """ + Test related model serializer inherits the parent serializer kwargs. + Specifically, tests that child resources will have the `view` as the + parent, addressing issue #214. + """ + class NestedM2(Resource): + fields = ('field1', ) + def field1(self, obj): + return self.view + obj.field1 + + class NestedM3(Resource): + fields = ('field2', ) + def field2(self, obj): + return self.view + obj.field2 + + class SerializerM2(Resource): + fields = [('field', NestedM2)] + + class SerializerM3(Resource): + fields = [('field', NestedM3)] + + self.assertEqual(SerializerM2(view=u'hello').serialize(self.m2), {'field': {'field1': u'hellofoo'}}) + self.assertEqual(SerializerM3(view=u'goodbye').serialize(self.m3), {'field': {'field2': u'goodbyebar'}}) + def test_serializer_overridden_hook_method(self): """ Test serializing a model instance which overrides a class method on the