55from collections import OrderedDict
66
77import inflection
8+ from django .db .models import Manager , QuerySet
89from django .utils import six , encoding
910from rest_framework import relations
1011from rest_framework import renderers
11- from rest_framework .serializers import BaseSerializer , ListSerializer , ModelSerializer
12+ from rest_framework .serializers import BaseSerializer , Serializer , ListSerializer , ModelSerializer
1213from rest_framework .settings import api_settings
1314
1415from . import utils
@@ -88,25 +89,28 @@ def extract_relationships(fields, resource, resource_instance):
8889
8990 source = field .source
9091 try :
91- relation_instance_or_manager = getattr (resource_instance , source )
92+ relation_instance = getattr (resource_instance , source )
9293 except AttributeError :
9394 # if the field is not defined on the model then we check the serializer
9495 # and if no value is there we skip over the field completely
9596 serializer_method = getattr (field .parent , source , None )
9697 if serializer_method and hasattr (serializer_method , '__call__' ):
97- relation_instance_or_manager = serializer_method (resource_instance )
98+ relation_instance = serializer_method (resource_instance )
9899 else :
99100 continue
100101
102+ if isinstance (relation_instance , Manager ):
103+ relation_instance = relation_instance .all ()
104+
101105 relation_type = utils .get_related_resource_type (field )
102106
103107 if isinstance (field , relations .HyperlinkedIdentityField ):
104108 # special case for HyperlinkedIdentityField
105109 relation_data = list ()
106110
107111 # Don't try to query an empty relation
108- relation_queryset = relation_instance_or_manager . all () \
109- if relation_instance_or_manager is not None else list ()
112+ relation_queryset = relation_instance \
113+ if relation_instance is not None else list ()
110114
111115 for related_object in relation_queryset :
112116 relation_data .append (
@@ -138,7 +142,7 @@ def extract_relationships(fields, resource, resource_instance):
138142 continue
139143
140144 if isinstance (field , (relations .PrimaryKeyRelatedField , relations .HyperlinkedRelatedField )):
141- relation_id = relation_instance_or_manager .pk if resource .get (field_name ) else None
145+ relation_id = relation_instance .pk if resource .get (field_name ) else None
142146
143147 relation_data = {
144148 'data' : (
@@ -177,11 +181,15 @@ def extract_relationships(fields, resource, resource_instance):
177181 continue
178182
179183 relation_data = list ()
180- for related_object in relation_instance_or_manager .all ():
181- related_object_type = utils .get_instance_or_manager_resource_type (related_object )
184+ for nested_resource_instance in relation_instance :
185+ nested_resource_instance_type = (
186+ relation_type or
187+ utils .get_resource_type_from_instance (nested_resource_instance )
188+ )
189+
182190 relation_data .append (OrderedDict ([
183- ('type' , related_object_type ),
184- ('id' , encoding .force_text (related_object .pk ))
191+ ('type' , nested_resource_instance_type ),
192+ ('id' , encoding .force_text (nested_resource_instance .pk ))
185193 ]))
186194 data .update ({
187195 field_name : {
@@ -193,15 +201,19 @@ def extract_relationships(fields, resource, resource_instance):
193201 })
194202 continue
195203
196- if isinstance (field , ListSerializer ):
204+ if isinstance (field , ListSerializer ) and relation_instance is not None :
197205 relation_data = list ()
198206
199207 serializer_data = resource .get (field_name )
200- resource_instance_queryset = list (relation_instance_or_manager . all () )
208+ resource_instance_queryset = list (relation_instance )
201209 if isinstance (serializer_data , list ):
202210 for position in range (len (serializer_data )):
203211 nested_resource_instance = resource_instance_queryset [position ]
204- nested_resource_instance_type = utils .get_resource_type_from_instance (nested_resource_instance )
212+ nested_resource_instance_type = (
213+ relation_type or
214+ utils .get_resource_type_from_instance (nested_resource_instance )
215+ )
216+
205217 relation_data .append (OrderedDict ([
206218 ('type' , nested_resource_instance_type ),
207219 ('id' , encoding .force_text (nested_resource_instance .pk ))
@@ -210,16 +222,13 @@ def extract_relationships(fields, resource, resource_instance):
210222 data .update ({field_name : {'data' : relation_data }})
211223 continue
212224
213- if isinstance (field , ModelSerializer ):
214- relation_model = field .Meta .model
215- relation_type = utils .format_resource_type (relation_model .__name__ )
216-
225+ if isinstance (field , Serializer ):
217226 data .update ({
218227 field_name : {
219228 'data' : (
220229 OrderedDict ([
221230 ('type' , relation_type ),
222- ('id' , encoding .force_text (relation_instance_or_manager .pk ))
231+ ('id' , encoding .force_text (relation_instance .pk ))
223232 ]) if resource .get (field_name ) else None )
224233 }
225234 })
@@ -258,38 +267,41 @@ def extract_included(fields, resource, resource_instance, included_resources):
258267 continue
259268
260269 try :
261- relation_instance_or_manager = getattr (resource_instance , field_name )
270+ relation_instance = getattr (resource_instance , field_name )
262271 except AttributeError :
263272 try :
264273 # For ManyRelatedFields if `related_name` is not set we need to access `foo_set` from `source`
265- relation_instance_or_manager = getattr (resource_instance , field .child_relation .source )
274+ relation_instance = getattr (resource_instance , field .child_relation .source )
266275 except AttributeError :
267276 if not hasattr (current_serializer , field .source ):
268277 continue
269278 serializer_method = getattr (current_serializer , field .source )
270- relation_instance_or_manager = serializer_method (resource_instance )
279+ relation_instance = serializer_method (resource_instance )
280+
281+ if isinstance (relation_instance , Manager ):
282+ relation_instance = relation_instance .all ()
271283
272284 new_included_resources = [key .replace ('%s.' % field_name , '' , 1 )
273285 for key in included_resources
274286 if field_name == key .split ('.' )[0 ]]
275287 serializer_data = resource .get (field_name )
276288
277289 if isinstance (field , relations .ManyRelatedField ):
278- serializer_class = included_serializers . get ( field_name )
279- field = serializer_class (relation_instance_or_manager . all () , many = True , context = context )
290+ serializer_class = included_serializers [ field_name ]
291+ field = serializer_class (relation_instance , many = True , context = context )
280292 serializer_data = field .data
281293
282294 if isinstance (field , relations .RelatedField ):
283- serializer_class = included_serializers .get (field_name )
284- if relation_instance_or_manager is None :
295+ if relation_instance is None :
285296 continue
286- field = serializer_class (relation_instance_or_manager , context = context )
297+ serializer_class = included_serializers [field_name ]
298+ field = serializer_class (relation_instance , context = context )
287299 serializer_data = field .data
288300
289301 if isinstance (field , ListSerializer ):
290302 serializer = field .child
291303 relation_type = utils .get_resource_type_from_serializer (serializer )
292- relation_queryset = list (relation_instance_or_manager . all () )
304+ relation_queryset = list (relation_instance )
293305
294306 # Get the serializer fields
295307 serializer_fields = utils .get_serializer_fields (serializer )
@@ -312,7 +324,7 @@ def extract_included(fields, resource, resource_instance, included_resources):
312324 )
313325 )
314326
315- if isinstance (field , ModelSerializer ):
327+ if isinstance (field , Serializer ):
316328
317329 relation_type = utils .get_resource_type_from_serializer (field )
318330
@@ -322,11 +334,11 @@ def extract_included(fields, resource, resource_instance, included_resources):
322334 included_data .append (
323335 JSONRenderer .build_json_resource_obj (
324336 serializer_fields , serializer_data ,
325- relation_instance_or_manager , relation_type )
337+ relation_instance , relation_type )
326338 )
327339 included_data .extend (
328340 JSONRenderer .extract_included (
329- serializer_fields , serializer_data , relation_instance_or_manager , new_included_resources
341+ serializer_fields , serializer_data , relation_instance , new_included_resources
330342 )
331343 )
332344
0 commit comments