tomchristie/django-rest-framework — pull request #802 by chenjyw (2013-04-28 19:46:01+00:00)
Title: Fix nesting issue with depth >=2

Nesting does not currently work if you set depth to something greater than one. The reason is that self.opts.depth doesn't get set on NestedModelSerializer instances before the instance checks for relationship fields within itself, so those relationship fields do not get instantiated as NestedModelSerializers themselves.

def get_fields(self):
...
# Add in the default fields
default_fields = self.get_default_fields()
for key, val in default_fields.items():
if key not in ret:
ret[key] = val

...

for key, field in ret.items():
field.initialize(parent=self, field_name=key)

return ret

When get_default_fields() is called, relationship fields are instantiated as NestedModelSerializers by get_nested_field() if self.opts.depth is set. So with depth=2 let's say you have base_instance, nested_instance_level1, and nested_instance_level2. When nested_instance_level1 is instantiated by base_instance, nested_instance_level2 should also get instantiated in that moment because field processing all happens on init. In other words, when get_default_fields() is called on base_instance, all the nested instances are supposed to get instantiated recursively at that time.

However, field.initialize() doesn't get called in base_instance until after get_default_fields. This means that self.opts.depth is not set on nested_instance_level1 when it calls its own get_default_fields, so its relationship fields don't get instantiated as NestedModelSerializers. base_instance has no trouble instantiating nested_instance_level1 because we pass in "depth" through the serializer's meta options. The result is that only the first nesting level gets serialized no matter what you put for depth in the meta options.

So two commits here. One reimplements depth handling by setting the depth on the NestedModelSerializer definition in get_nested_field(), ensuring each instance always has self.opts.depth available on instantiation. The other modifies @gkappel's DepthTest so that it tests two levels of nesting.