Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b96d79d

Browse files
committed
Merge branch 'develop' of github.com:django-json-api/django-rest-framework-json-api into jarekwg-optimize/relationship-extraction
2 parents 04a100c + 0aedffb commit b96d79d

File tree

3 files changed

+122
-108
lines changed

3 files changed

+122
-108
lines changed

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pip-delete-this-directory.txt
2828
# Pycharm project files
2929
.idea/
3030

31+
# PyTest cache
32+
.cache/
33+
3134
# Tox
3235
.tox/
3336

‎rest_framework_json_api/renderers.py‎

Lines changed: 54 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
from collections import OrderedDict
66

77
import inflection
8+
from django.db.models import Manager, QuerySet
89
from django.utils import six, encoding
910
from rest_framework import relations
1011
from rest_framework import renderers
11-
from rest_framework.serializers import BaseSerializer, ListSerializer, ModelSerializer
12+
from rest_framework.serializers import BaseSerializer, Serializer, ListSerializer
1213
from rest_framework.settings import api_settings
1314

1415
from . import utils
@@ -87,24 +88,18 @@ def extract_relationships(fields, resource, resource_instance):
8788
continue
8889

8990
source = field.source
90-
serializer_method = getattr(field.parent, source, None)
9191
relation_type = utils.get_related_resource_type(field)
9292

9393
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
10297
# special case for HyperlinkedIdentityField
10398
relation_data = list()
10499

105100
# 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()
108103

109104
for related_object in relation_queryset:
110105
relation_data.append(
@@ -122,13 +117,9 @@ def extract_relationships(fields, resource, resource_instance):
122117
continue
123118

124119
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
132123

133124
# special case for ResourceRelatedField
134125
relation_data = {
@@ -144,14 +135,9 @@ def extract_relationships(fields, resource, resource_instance):
144135
continue
145136

146137
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
155141
relation_id = relation if resource.get(field_name) else None
156142
relation_data = {
157143
'data': (
@@ -167,13 +153,9 @@ def extract_relationships(fields, resource, resource_instance):
167153
continue
168154

169155
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
177159

178160
if isinstance(field.child_relation, ResourceRelatedField):
179161
# special case for ResourceRelatedField
@@ -197,11 +179,15 @@ def extract_relationships(fields, resource, resource_instance):
197179
continue
198180

199181
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+
202188
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))
205191
]))
206192
data.update({
207193
field_name: {
@@ -213,23 +199,23 @@ def extract_relationships(fields, resource, resource_instance):
213199
})
214200
continue
215201

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
224206

225207
relation_data = list()
226208

227209
serializer_data = resource.get(field_name)
228-
resource_instance_queryset = list(relation_instance_or_manager.all())
210+
resource_instance_queryset = list(relation_instance)
229211
if isinstance(serializer_data, list):
230212
for position in range(len(serializer_data)):
231213
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+
233219
relation_data.append(OrderedDict([
234220
('type', nested_resource_instance_type),
235221
('id', encoding.force_text(nested_resource_instance.pk))
@@ -238,24 +224,17 @@ def extract_relationships(fields, resource, resource_instance):
238224
data.update({field_name: {'data': relation_data}})
239225
continue
240226

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
252231

253232
data.update({
254233
field_name: {
255234
'data': (
256235
OrderedDict([
257236
('type', relation_type),
258-
('id', encoding.force_text(relation_instance_or_manager.pk))
237+
('id', encoding.force_text(relation_instance.pk))
259238
]) if resource.get(field_name) else None)
260239
}
261240
})
@@ -294,38 +273,41 @@ def extract_included(fields, resource, resource_instance, included_resources):
294273
continue
295274

296275
try:
297-
relation_instance_or_manager = getattr(resource_instance, field_name)
276+
relation_instance = getattr(resource_instance, field_name)
298277
except AttributeError:
299278
try:
300279
# 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)
302281
except AttributeError:
303282
if not hasattr(current_serializer, field.source):
304283
continue
305284
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()
307289

308290
new_included_resources = [key.replace('%s.' % field_name, '', 1)
309291
for key in included_resources
310292
if field_name == key.split('.')[0]]
311293
serializer_data = resource.get(field_name)
312294

313295
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)
316298
serializer_data = field.data
317299

318300
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:
321302
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)
323305
serializer_data = field.data
324306

325307
if isinstance(field, ListSerializer):
326308
serializer = field.child
327309
relation_type = utils.get_resource_type_from_serializer(serializer)
328-
relation_queryset = list(relation_instance_or_manager.all())
310+
relation_queryset = list(relation_instance)
329311

330312
# Get the serializer fields
331313
serializer_fields = utils.get_serializer_fields(serializer)
@@ -348,7 +330,7 @@ def extract_included(fields, resource, resource_instance, included_resources):
348330
)
349331
)
350332

351-
if isinstance(field, ModelSerializer):
333+
if isinstance(field, Serializer):
352334

353335
relation_type = utils.get_resource_type_from_serializer(field)
354336

@@ -358,11 +340,11 @@ def extract_included(fields, resource, resource_instance, included_resources):
358340
included_data.append(
359341
JSONRenderer.build_json_resource_obj(
360342
serializer_fields, serializer_data,
361-
relation_instance_or_manager, relation_type)
343+
relation_instance, relation_type)
362344
)
363345
included_data.extend(
364346
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
366348
)
367349
)
368350

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /