Skip to content

Commit ae720d9

Browse files
authored
Fix issue with generating categories for schema endpoints (#4394)
1 parent 7466b61 commit ae720d9

File tree

1 file changed

+38
-42
lines changed

1 file changed

+38
-42
lines changed

rest_framework/schemas.py

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class SchemaGenerator(object):
3939
'patch': 'partial_update',
4040
'delete': 'destroy',
4141
}
42+
known_actions = (
43+
'create', 'read', 'retrieve', 'list',
44+
'update', 'partial_update', 'destroy'
45+
)
4246

4347
def __init__(self, title=None, url=None, patterns=None, urlconf=None):
4448
assert coreapi, '`coreapi` must be installed for schema support.'
@@ -118,7 +122,8 @@ def get_api_endpoints(self, patterns, prefix=''):
118122
if self.should_include_endpoint(path, callback):
119123
for method in self.get_allowed_methods(callback):
120124
action = self.get_action(path, method, callback)
121-
endpoint = (path, method, action, callback)
125+
category = self.get_category(path, method, callback, action)
126+
endpoint = (path, method, category, action, callback)
122127
api_endpoints.append(endpoint)
123128

124129
elif isinstance(pattern, RegexURLResolver):
@@ -128,21 +133,7 @@ def get_api_endpoints(self, patterns, prefix=''):
128133
)
129134
api_endpoints.extend(nested_endpoints)
130135

131-
return self.add_categories(api_endpoints)
132-
133-
def add_categories(self, api_endpoints):
134-
"""
135-
(path, method, action, callback) -> (path, method, category, action, callback)
136-
"""
137-
# Determine the top level categories for the schema content,
138-
# based on the URLs of the endpoints. Eg `set(['users', 'organisations'])`
139-
paths = [endpoint[0] for endpoint in api_endpoints]
140-
categories = self.get_categories(paths)
141-
142-
return [
143-
(path, method, self.get_category(categories, path), action, callback)
144-
for (path, method, action, callback) in api_endpoints
145-
]
136+
return api_endpoints
146137

147138
def get_path(self, path_regex):
148139
"""
@@ -181,36 +172,41 @@ def get_allowed_methods(self, callback):
181172

182173
def get_action(self, path, method, callback):
183174
"""
184-
Return a description action string for the endpoint, eg. 'list'.
175+
Return a descriptive action string for the endpoint, eg. 'list'.
185176
"""
186177
actions = getattr(callback, 'actions', self.default_mapping)
187178
return actions[method.lower()]
188179

189-
def get_categories(self, paths):
190-
categories = set()
191-
split_paths = set([
192-
tuple(path.split("{")[0].strip('/').split('/'))
193-
for path in paths
194-
])
195-
196-
while split_paths:
197-
for split_path in list(split_paths):
198-
if len(split_path) == 0:
199-
split_paths.remove(split_path)
200-
elif len(split_path) == 1:
201-
categories.add(split_path[0])
202-
split_paths.remove(split_path)
203-
elif split_path[0] in categories:
204-
split_paths.remove(split_path)
205-
206-
return categories
207-
208-
def get_category(self, categories, path):
209-
path_components = path.split("{")[0].strip('/').split('/')
210-
for path_component in path_components:
211-
if path_component in categories:
212-
return path_component
213-
return None
180+
def get_category(self, path, method, callback, action):
181+
"""
182+
Return a descriptive category string for the endpoint, eg. 'users'.
183+
184+
Examples of category/action pairs that should be generated for various
185+
endpoints:
186+
187+
/users/ [users][list], [users][create]
188+
/users/{pk}/ [users][read], [users][update], [users][destroy]
189+
/users/enabled/ [users][enabled] (custom action)
190+
/users/{pk}/star/ [users][star] (custom action)
191+
/users/{pk}/groups/ [groups][list], [groups][create]
192+
/users/{pk}/groups/{pk}/ [groups][read], [groups][update], [groups][destroy]
193+
"""
194+
path_components = path.strip('/').split('/')
195+
path_components = [
196+
component for component in path_components
197+
if '{' not in component
198+
]
199+
if action in self.known_actions:
200+
# Default action, eg "/users/", "/users/{pk}/"
201+
idx = -1
202+
else:
203+
# Custom action, eg "/users/{pk}/activate/", "/users/active/"
204+
idx = -2
205+
206+
try:
207+
return path_components[idx]
208+
except IndexError:
209+
return None
214210

215211
# Methods for generating each individual `Link` instance...
216212

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy