1111from rest_framework .settings import api_settings
1212from rest_framework .exceptions import APIException
1313
14-
1514try :
1615 from rest_framework .compat import OrderedDict
1716except ImportError :
@@ -190,7 +189,6 @@ def get_related_resource_type(relation):
190189
191190
192191def get_instance_or_manager_resource_type (resource_instance_or_manager ):
193-
194192 if hasattr (resource_instance_or_manager , 'model' ):
195193 return get_resource_type_from_manager (resource_instance_or_manager )
196194 if hasattr (resource_instance_or_manager , '_meta' ):
@@ -396,19 +394,45 @@ def extract_relationships(fields, resource, resource_instance):
396394 return format_keys (data )
397395
398396
399- def extract_included (fields , resource , resource_instance ):
397+ def extract_included (fields , resource , resource_instance , included_resources ):
400398 included_data = list ()
399+
400+ current_serializer = fields .serializer
401+ context = current_serializer .context
402+ included_serializers = getattr (fields .serializer , 'included_serializers' , None )
403+
404+ included_serializers = {
405+ key : current_serializer .__class__ if serializer == 'self' else serializer
406+ for key , serializer in included_serializers .items ()
407+ } if included_serializers else dict ()
408+
401409 for field_name , field in six .iteritems (fields ):
402410 # Skip URL field
403411 if field_name == api_settings .URL_FIELD_NAME :
404412 continue
405413
406- # Skip fields without serialized data
407- if not isinstance (field , BaseSerializer ):
414+ # Skip fields without relations or serialized data
415+ if not isinstance (field , (RelatedField , ManyRelatedField , BaseSerializer )):
416+ continue
417+
418+ try :
419+ included_resources .remove (field_name )
420+ relation_instance_or_manager = getattr (resource_instance , field_name )
421+ serializer_data = resource .get (field_name )
422+ new_included_resources = [key .replace ('%s.' % field_name , '' , 1 ) for key in included_resources ]
423+ except ValueError :
424+ # Skip fields not in requested included resources
408425 continue
409426
410- relation_instance_or_manager = getattr (resource_instance , field_name )
411- serializer_data = resource .get (field_name )
427+ if isinstance (field , ManyRelatedField ):
428+ serializer_class = included_serializers .get (field_name )
429+ field = serializer_class (relation_instance_or_manager .all (), many = True , context = context )
430+ serializer_data = field .data
431+
432+ if isinstance (field , RelatedField ):
433+ serializer_class = included_serializers .get (field_name )
434+ field = serializer_class (relation_instance_or_manager , context = context )
435+ serializer_data = field .data
412436
413437 if isinstance (field , ListSerializer ):
414438 serializer = field .child
@@ -427,6 +451,11 @@ def extract_included(fields, resource, resource_instance):
427451 serializer_fields , serializer_resource , nested_resource_instance , relation_type
428452 )
429453 )
454+ included_data .extend (
455+ extract_included (
456+ serializer_fields , serializer_resource , nested_resource_instance , new_included_resources
457+ )
458+ )
430459
431460 if isinstance (field , ModelSerializer ):
432461 model = field .Meta .model
@@ -436,7 +465,13 @@ def extract_included(fields, resource, resource_instance):
436465 serializer_fields = get_serializer_fields (field )
437466 if serializer_data :
438467 included_data .append (
439- build_json_resource_obj (serializer_fields , serializer_data , relation_instance_or_manager , relation_type )
468+ build_json_resource_obj (serializer_fields , serializer_data , relation_instance_or_manager ,
469+ relation_type )
470+ )
471+ included_data .extend (
472+ extract_included (
473+ serializer_fields , serializer_data , relation_instance_or_manager , new_included_resources
474+ )
440475 )
441476
442477 return format_keys (included_data )
0 commit comments