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 7dd12a1

Browse files
committed
Revert "simplify relationships paths"
This reverts commit 5855b65.
1 parent 5855b65 commit 7dd12a1

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

‎example/tests/test_openapi.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ def test_schema_construction():
128128
def test_schema_related_serializers():
129129
"""
130130
Confirm that paths are generated for related fields. For example:
131-
/authors/{pk}/{related_field>}
131+
url path '/authors/{pk}/{related_field>}/' generates:
132+
/authors/{id}/relationships/comments/
133+
/authors/{id}/relationships/entries/
134+
/authors/{id}/relationships/first_entry/ -- Maybe?
132135
/authors/{id}/comments/
133136
/authors/{id}/entries/
134137
/authors/{id}/first_entry/
@@ -138,7 +141,12 @@ def test_schema_related_serializers():
138141
request = create_request('/')
139142
schema = generator.get_schema(request=request)
140143
# make sure the path's relationship and related {related_field}'s got expanded
141-
assert '/authors/{id}/relationships/{related_field}' in schema['paths']
144+
assert '/authors/{id}/relationships/entries' in schema['paths']
145+
assert '/authors/{id}/relationships/comments' in schema['paths']
146+
# first_entry is a special case (SerializerMethodRelatedField)
147+
# TODO: '/authors/{id}/relationships/first_entry' supposed to be there?
148+
# It fails when doing the actual GET, so this schema excluding it is OK.
149+
# assert '/authors/{id}/relationships/first_entry/' in schema['paths']
142150
assert '/authors/{id}/comments/' in schema['paths']
143151
assert '/authors/{id}/entries/' in schema['paths']
144152
assert '/authors/{id}/first_entry/' in schema['paths']

‎rest_framework_json_api/schemas/openapi.py‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import warnings
22
from urllib.parse import urljoin
33

4+
from django.db.models.fields import related_descriptors as rd
45
from django.utils.module_loading import import_string as import_class_from_dotted_path
56
from rest_framework.fields import empty
67
from rest_framework.relations import ManyRelatedField
78
from rest_framework.schemas import openapi as drf_openapi
89
from rest_framework.schemas.utils import is_list_view
910

1011
from rest_framework_json_api import serializers
12+
from rest_framework_json_api.views import RelationshipView
1113

1214

1315
class SchemaGenerator(drf_openapi.SchemaGenerator):
@@ -300,7 +302,9 @@ def get_schema(self, request=None, public=False):
300302
#: - 'action' copy of current view.action (list/fetch) as this gets reset for each request.
301303
expanded_endpoints = []
302304
for path, method, view in view_endpoints:
303-
if hasattr(view, 'action') and view.action == 'retrieve_related':
305+
if isinstance(view, RelationshipView):
306+
expanded_endpoints += self._expand_relationships(path, method, view)
307+
elif hasattr(view, 'action') and view.action == 'retrieve_related':
304308
expanded_endpoints += self._expand_related(path, method, view, view_endpoints)
305309
else:
306310
expanded_endpoints.append((path, method, view, getattr(view, 'action', None)))
@@ -346,6 +350,28 @@ def get_schema(self, request=None, public=False):
346350

347351
return schema
348352

353+
def _expand_relationships(self, path, method, view):
354+
"""
355+
Expand path containing .../{id}/relationships/{related_field} into list of related fields.
356+
:return:list[tuple(path, method, view, action)]
357+
"""
358+
queryset = view.get_queryset()
359+
if not queryset.model:
360+
return [(path, method, view, getattr(view, 'action', '')), ]
361+
result = []
362+
# TODO: what about serializer-only (non-model) fields?
363+
# Shouldn't this be iterating over serializer fields rather than model fields?
364+
# Look at parent view's serializer to get the list of fields.
365+
# OR maybe like _expand_related?
366+
m = queryset.model
367+
for field in [f for f in dir(m) if not f.startswith('_')]:
368+
attr = getattr(m, field)
369+
if isinstance(attr, (rd.ReverseManyToOneDescriptor, rd.ForwardOneToOneDescriptor)):
370+
action = 'rels' if isinstance(attr, rd.ReverseManyToOneDescriptor) else 'rel'
371+
result.append((path.replace('{related_field}', field), method, view, action))
372+
373+
return result
374+
349375
def _expand_related(self, path, method, view, view_endpoints):
350376
"""
351377
Expand path containing .../{id}/{related_field} into list of related fields

0 commit comments

Comments
(0)

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