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
12
13
from rest_framework .settings import api_settings
13
14
14
15
from . import utils
@@ -87,24 +88,18 @@ def extract_relationships(fields, resource, resource_instance):
87
88
continue
88
89
89
90
source = field .source
90
- serializer_method = getattr (field .parent , source , None )
91
91
relation_type = utils .get_related_resource_type (field )
92
92
93
93
if isinstance (field , relations .HyperlinkedIdentityField ):
94
- try :
95
- relation_instance_or_manager = getattr (resource_instance , source )
96
- except AttributeError :
97
- if serializer_method and hasattr (serializer_method , '__call__' ):
98
- relation_instance_or_manager = serializer_method (resource_instance )
99
- else :
100
- continue
101
-
94
+ resolved , relation_instance = utils .get_relation_instance (resource_instance , source , field .parent )
95
+ if not resolved :
96
+ continue
102
97
# special case for HyperlinkedIdentityField
103
98
relation_data = list ()
104
99
105
100
# Don't try to query an empty relation
106
- relation_queryset = relation_instance_or_manager . all () \
107
- if relation_instance_or_manager is not None else list ()
101
+ relation_queryset = relation_instance \
102
+ if relation_instance is not None else list ()
108
103
109
104
for related_object in relation_queryset :
110
105
relation_data .append (
@@ -122,13 +117,9 @@ def extract_relationships(fields, resource, resource_instance):
122
117
continue
123
118
124
119
if isinstance (field , ResourceRelatedField ):
125
- try :
126
- relation_instance_or_manager = getattr (resource_instance , source )
127
- except AttributeError :
128
- if serializer_method and hasattr (serializer_method , '__call__' ):
129
- relation_instance_or_manager = serializer_method (resource_instance )
130
- else :
131
- continue
120
+ resolved , relation_instance = utils .get_relation_instance (resource_instance , source , field .parent )
121
+ if not resolved :
122
+ continue
132
123
133
124
# special case for ResourceRelatedField
134
125
relation_data = {
@@ -144,14 +135,9 @@ def extract_relationships(fields, resource, resource_instance):
144
135
continue
145
136
146
137
if isinstance (field , (relations .PrimaryKeyRelatedField , relations .HyperlinkedRelatedField )):
147
- try :
148
- relation = getattr (resource_instance , '%s_id' % field .source )
149
- except AttributeError :
150
- if serializer_method and hasattr (serializer_method , '__call__' ):
151
- relation = serializer_method (resource_instance ).pk
152
- else :
153
- continue
154
-
138
+ resolved , relation = utils .get_relation_instance (resource_instance , '%s_id' % source , field .parent )
139
+ if not resolved :
140
+ continue
155
141
relation_id = relation if resource .get (field_name ) else None
156
142
relation_data = {
157
143
'data' : (
@@ -167,13 +153,9 @@ def extract_relationships(fields, resource, resource_instance):
167
153
continue
168
154
169
155
if isinstance (field , relations .ManyRelatedField ):
170
- try :
171
- relation_instance_or_manager = getattr (resource_instance , source )
172
- except AttributeError :
173
- if serializer_method and hasattr (serializer_method , '__call__' ):
174
- relation_instance_or_manager = serializer_method (resource_instance )
175
- else :
176
- continue
156
+ resolved , relation_instance = utils .get_relation_instance (resource_instance , source , field .parent )
157
+ if not resolved :
158
+ continue
177
159
178
160
if isinstance (field .child_relation , ResourceRelatedField ):
179
161
# special case for ResourceRelatedField
@@ -197,11 +179,15 @@ def extract_relationships(fields, resource, resource_instance):
197
179
continue
198
180
199
181
relation_data = list ()
200
- for related_object in relation_instance_or_manager .all ():
201
- related_object_type = utils .get_instance_or_manager_resource_type (related_object )
182
+ for nested_resource_instance in relation_instance :
183
+ nested_resource_instance_type = (
184
+ relation_type or
185
+ utils .get_resource_type_from_instance (nested_resource_instance )
186
+ )
187
+
202
188
relation_data .append (OrderedDict ([
203
- ('type' , related_object_type ),
204
- ('id' , encoding .force_text (related_object .pk ))
189
+ ('type' , nested_resource_instance_type ),
190
+ ('id' , encoding .force_text (nested_resource_instance .pk ))
205
191
]))
206
192
data .update ({
207
193
field_name : {
@@ -213,23 +199,23 @@ def extract_relationships(fields, resource, resource_instance):
213
199
})
214
200
continue
215
201
216
- if isinstance (field , ListSerializer ):
217
- try :
218
- relation_instance_or_manager = getattr (resource_instance , source )
219
- except AttributeError :
220
- if serializer_method and hasattr (serializer_method , '__call__' ):
221
- relation_instance_or_manager = serializer_method (resource_instance )
222
- else :
223
- continue
202
+ if isinstance (field , ListSerializer ) and relation_instance is not None :
203
+ resolved , relation_instance = utils .get_relation_instance (resource_instance , source , field .parent )
204
+ if not resolved :
205
+ continue
224
206
225
207
relation_data = list ()
226
208
227
209
serializer_data = resource .get (field_name )
228
- resource_instance_queryset = list (relation_instance_or_manager . all () )
210
+ resource_instance_queryset = list (relation_instance )
229
211
if isinstance (serializer_data , list ):
230
212
for position in range (len (serializer_data )):
231
213
nested_resource_instance = resource_instance_queryset [position ]
232
- nested_resource_instance_type = utils .get_resource_type_from_instance (nested_resource_instance )
214
+ nested_resource_instance_type = (
215
+ relation_type or
216
+ utils .get_resource_type_from_instance (nested_resource_instance )
217
+ )
218
+
233
219
relation_data .append (OrderedDict ([
234
220
('type' , nested_resource_instance_type ),
235
221
('id' , encoding .force_text (nested_resource_instance .pk ))
@@ -238,24 +224,17 @@ def extract_relationships(fields, resource, resource_instance):
238
224
data .update ({field_name : {'data' : relation_data }})
239
225
continue
240
226
241
- if isinstance (field , ModelSerializer ):
242
- try :
243
- relation_instance_or_manager = getattr (resource_instance , source )
244
- except AttributeError :
245
- if serializer_method and hasattr (serializer_method , '__call__' ):
246
- relation_instance_or_manager = serializer_method (resource_instance )
247
- else :
248
- continue
249
-
250
- relation_model = field .Meta .model
251
- relation_type = utils .format_resource_type (relation_model .__name__ )
227
+ if isinstance (field , Serializer ):
228
+ resolved , relation_instance = utils .get_relation_instance (resource_instance , source , field .parent )
229
+ if not resolved :
230
+ continue
252
231
253
232
data .update ({
254
233
field_name : {
255
234
'data' : (
256
235
OrderedDict ([
257
236
('type' , relation_type ),
258
- ('id' , encoding .force_text (relation_instance_or_manager .pk ))
237
+ ('id' , encoding .force_text (relation_instance .pk ))
259
238
]) if resource .get (field_name ) else None )
260
239
}
261
240
})
@@ -294,38 +273,41 @@ def extract_included(fields, resource, resource_instance, included_resources):
294
273
continue
295
274
296
275
try :
297
- relation_instance_or_manager = getattr (resource_instance , field_name )
276
+ relation_instance = getattr (resource_instance , field_name )
298
277
except AttributeError :
299
278
try :
300
279
# For ManyRelatedFields if `related_name` is not set we need to access `foo_set` from `source`
301
- relation_instance_or_manager = getattr (resource_instance , field .child_relation .source )
280
+ relation_instance = getattr (resource_instance , field .child_relation .source )
302
281
except AttributeError :
303
282
if not hasattr (current_serializer , field .source ):
304
283
continue
305
284
serializer_method = getattr (current_serializer , field .source )
306
- relation_instance_or_manager = serializer_method (resource_instance )
285
+ relation_instance = serializer_method (resource_instance )
286
+
287
+ if isinstance (relation_instance , Manager ):
288
+ relation_instance = relation_instance .all ()
307
289
308
290
new_included_resources = [key .replace ('%s.' % field_name , '' , 1 )
309
291
for key in included_resources
310
292
if field_name == key .split ('.' )[0 ]]
311
293
serializer_data = resource .get (field_name )
312
294
313
295
if isinstance (field , relations .ManyRelatedField ):
314
- serializer_class = included_serializers . get ( field_name )
315
- field = serializer_class (relation_instance_or_manager . all () , many = True , context = context )
296
+ serializer_class = included_serializers [ field_name ]
297
+ field = serializer_class (relation_instance , many = True , context = context )
316
298
serializer_data = field .data
317
299
318
300
if isinstance (field , relations .RelatedField ):
319
- serializer_class = included_serializers .get (field_name )
320
- if relation_instance_or_manager is None :
301
+ if relation_instance is None :
321
302
continue
322
- field = serializer_class (relation_instance_or_manager , context = context )
303
+ serializer_class = included_serializers [field_name ]
304
+ field = serializer_class (relation_instance , context = context )
323
305
serializer_data = field .data
324
306
325
307
if isinstance (field , ListSerializer ):
326
308
serializer = field .child
327
309
relation_type = utils .get_resource_type_from_serializer (serializer )
328
- relation_queryset = list (relation_instance_or_manager . all () )
310
+ relation_queryset = list (relation_instance )
329
311
330
312
# Get the serializer fields
331
313
serializer_fields = utils .get_serializer_fields (serializer )
@@ -348,7 +330,7 @@ def extract_included(fields, resource, resource_instance, included_resources):
348
330
)
349
331
)
350
332
351
- if isinstance (field , ModelSerializer ):
333
+ if isinstance (field , Serializer ):
352
334
353
335
relation_type = utils .get_resource_type_from_serializer (field )
354
336
@@ -358,11 +340,11 @@ def extract_included(fields, resource, resource_instance, included_resources):
358
340
included_data .append (
359
341
JSONRenderer .build_json_resource_obj (
360
342
serializer_fields , serializer_data ,
361
- relation_instance_or_manager , relation_type )
343
+ relation_instance , relation_type )
362
344
)
363
345
included_data .extend (
364
346
JSONRenderer .extract_included (
365
- serializer_fields , serializer_data , relation_instance_or_manager , new_included_resources
347
+ serializer_fields , serializer_data , relation_instance , new_included_resources
366
348
)
367
349
)
368
350
0 commit comments