Так что я отвечу на свой вопрос. Я взглянул на исходный код DRF для генерации схемы. Я разработал план и выполнил следующие шаги.
I подкласс класса SchemaGenerator, определенный в модуле rest_framework.schemas
. Ниже приведен код.
class CoreAPISchemaGenerator(SchemaGenerator):
def get_links(self, request=None, **kwargs):
links = LinkNode()
paths = list()
view_endpoints = list()
for path, method, callback in self.endpoints:
view = self.create_view(callback, method, request)
path = self.coerce_path(path, method, view)
paths.append(path)
view_endpoints.append((path, method, view))
if not paths:
return None
prefix = self.determine_path_prefix(paths)
for path, method, view in view_endpoints:
if not self.has_view_permissions(path, method, view):
continue
actions = getattr(view, 'actions', None)
schemas = getattr(view, 'schemas', None)
if not schemas:
link = view.schema.get_link(path, method, base_url=self.url)
subpath = path[len(prefix):]
keys = self.get_keys(subpath, method, view, view.schema)
insert_into(links, keys, link)
else:
action_map = getattr(view, 'action_map', None)
method_name = action_map.get(method.lower())
schema = schemas.get(method_name)
link = schema.get_link(path, method, base_url=self.url)
subpath = path[len(prefix):]
keys = self.get_keys(subpath, method, view, schema)
insert_into(links, keys, link)
return links
def get_keys(self, subpath, method, view, schema=None):
if schema and hasattr(schema, 'endpoint_name'):
return [schema.endpoint_name]
else:
if hasattr(view, 'action'):
action = view.action
else:
if is_list_view(subpath, method, view):
action = 'list'
else:
action = self.default_mapping[method.lower()]
named_path_components = [
component for component
in subpath.strip('/').split('/')
if '{' not in component
]
if is_custom_action(action):
if len(view.action_map) > 1:
action = self.default_mapping[method.lower()]
if action in self.coerce_method_names:
action = self.coerce_method_names[action]
return named_path_components + [action]
else:
return named_path_components[:-1] + [action]
if action in self.coerce_method_names:
action = self.coerce_method_names[action]
return named_path_components + [action]
Я специально изменил две функции get_links и get_keys , так как они позволяют мне достичь того, что я хотел.
Далее, для всех функций в наборах, которые я писал, я выделил для него отдельную схему. Я просто создал словарь, чтобы сохранить сопоставления имени функции с экземпляром схемы. Для лучшего подхода я создал отдельный файл для хранения схем. Например, если у меня был viewset Clients
, я создал соответствующий класс ClientsSchema
и внутри с определенными статическими методами, которые возвращали экземпляры схемы.
Пример
В файле, где я определяю свои схемы,
class ClientsSchema():
@staticmethod
def list_schema():
schema = schemas.ManualSchema(
fields=[],
description=''
)
schema.endpoint_name = 'Clients Listing'
return schema
В моем apis.py,
class Clients(viewsets.ViewSet):
schemas = {
'list': ClientsSchema.list_schema()
}
def list(self, request, **kwargs):
pass
Эта настройка позволяет мне определять схемы для любого типа функций, которые я добавляю в мои наборы просмотра. В дополнение к этому, я также хотел, чтобы конечные точки имели идентифицируемое имя, а не имя, сгенерированное DRF, как a > b > update > update
.
Для этого я добавил endpoint_name
свойство к schema
возвращаемому объекту. Эта часть обрабатывается в функции get_keys
, которая переопределяется.
Наконец, в urls.py, куда мы включаем URL для документации, нам нужно использовать наш генератор пользовательских схем. Как то так,
urlpatterns.append(url(r'^livedocs/', include_docs_urls(title='My Services', generator_class=CoreAPISchemaGenerator)))
В целях безопасности я не могу поделиться снимками. Извиняюсь за это. Надеюсь, это поможет.