5
5
from collections import OrderedDict
6
6
7
7
import inflection
8
+ from django .db .models import Manager , QuerySet
8
9
from django .utils import six , encoding
9
10
from rest_framework import relations
10
11
from rest_framework import renderers
11
- from rest_framework .serializers import BaseSerializer , ListSerializer , ModelSerializer
12
+ from rest_framework .serializers import BaseSerializer , Serializer , ListSerializer , ModelSerializer
12
13
from rest_framework .settings import api_settings
13
14
14
15
from . import utils
@@ -88,25 +89,28 @@ def extract_relationships(fields, resource, resource_instance):
88
89
89
90
source = field .source
90
91
try :
91
- relation_instance_or_manager = getattr (resource_instance , source )
92
+ relation_instance = getattr (resource_instance , source )
92
93
except AttributeError :
93
94
# if the field is not defined on the model then we check the serializer
94
95
# and if no value is there we skip over the field completely
95
96
serializer_method = getattr (field .parent , source , None )
96
97
if serializer_method and hasattr (serializer_method , '__call__' ):
97
- relation_instance_or_manager = serializer_method (resource_instance )
98
+ relation_instance = serializer_method (resource_instance )
98
99
else :
99
100
continue
100
101
102
+ if isinstance (relation_instance , Manager ):
103
+ relation_instance = relation_instance .all ()
104
+
101
105
relation_type = utils .get_related_resource_type (field )
102
106
103
107
if isinstance (field , relations .HyperlinkedIdentityField ):
104
108
# special case for HyperlinkedIdentityField
105
109
relation_data = list ()
106
110
107
111
# 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 ()
110
114
111
115
for related_object in relation_queryset :
112
116
relation_data .append (
@@ -138,7 +142,7 @@ def extract_relationships(fields, resource, resource_instance):
138
142
continue
139
143
140
144
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
142
146
143
147
relation_data = {
144
148
'data' : (
@@ -177,11 +181,15 @@ def extract_relationships(fields, resource, resource_instance):
177
181
continue
178
182
179
183
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
+
182
190
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 ))
185
193
]))
186
194
data .update ({
187
195
field_name : {
@@ -193,15 +201,19 @@ def extract_relationships(fields, resource, resource_instance):
193
201
})
194
202
continue
195
203
196
- if isinstance (field , ListSerializer ):
204
+ if isinstance (field , ListSerializer ) and relation_instance is not None :
197
205
relation_data = list ()
198
206
199
207
serializer_data = resource .get (field_name )
200
- resource_instance_queryset = list (relation_instance_or_manager . all () )
208
+ resource_instance_queryset = list (relation_instance )
201
209
if isinstance (serializer_data , list ):
202
210
for position in range (len (serializer_data )):
203
211
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
+
205
217
relation_data .append (OrderedDict ([
206
218
('type' , nested_resource_instance_type ),
207
219
('id' , encoding .force_text (nested_resource_instance .pk ))
@@ -210,16 +222,13 @@ def extract_relationships(fields, resource, resource_instance):
210
222
data .update ({field_name : {'data' : relation_data }})
211
223
continue
212
224
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 ):
217
226
data .update ({
218
227
field_name : {
219
228
'data' : (
220
229
OrderedDict ([
221
230
('type' , relation_type ),
222
- ('id' , encoding .force_text (relation_instance_or_manager .pk ))
231
+ ('id' , encoding .force_text (relation_instance .pk ))
223
232
]) if resource .get (field_name ) else None )
224
233
}
225
234
})
@@ -258,38 +267,41 @@ def extract_included(fields, resource, resource_instance, included_resources):
258
267
continue
259
268
260
269
try :
261
- relation_instance_or_manager = getattr (resource_instance , field_name )
270
+ relation_instance = getattr (resource_instance , field_name )
262
271
except AttributeError :
263
272
try :
264
273
# 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 )
266
275
except AttributeError :
267
276
if not hasattr (current_serializer , field .source ):
268
277
continue
269
278
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 ()
271
283
272
284
new_included_resources = [key .replace ('%s.' % field_name , '' , 1 )
273
285
for key in included_resources
274
286
if field_name == key .split ('.' )[0 ]]
275
287
serializer_data = resource .get (field_name )
276
288
277
289
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 )
280
292
serializer_data = field .data
281
293
282
294
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 :
285
296
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 )
287
299
serializer_data = field .data
288
300
289
301
if isinstance (field , ListSerializer ):
290
302
serializer = field .child
291
303
relation_type = utils .get_resource_type_from_serializer (serializer )
292
- relation_queryset = list (relation_instance_or_manager . all () )
304
+ relation_queryset = list (relation_instance )
293
305
294
306
# Get the serializer fields
295
307
serializer_fields = utils .get_serializer_fields (serializer )
@@ -312,7 +324,7 @@ def extract_included(fields, resource, resource_instance, included_resources):
312
324
)
313
325
)
314
326
315
- if isinstance (field , ModelSerializer ):
327
+ if isinstance (field , Serializer ):
316
328
317
329
relation_type = utils .get_resource_type_from_serializer (field )
318
330
@@ -322,11 +334,11 @@ def extract_included(fields, resource, resource_instance, included_resources):
322
334
included_data .append (
323
335
JSONRenderer .build_json_resource_obj (
324
336
serializer_fields , serializer_data ,
325
- relation_instance_or_manager , relation_type )
337
+ relation_instance , relation_type )
326
338
)
327
339
included_data .extend (
328
340
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
330
342
)
331
343
)
332
344
0 commit comments