Генерация схемы для действий набора представлений остальной структуры Django - PullRequest
0 голосов
/ 05 ноября 2018

Согласно документации DRF, я начал использовать ViewSet и реализовал list, retrieve, create, update and destroy действия. У меня есть другой APIView, для которого я смог написать схему (ManualSchema), и когда я перехожу к /docs/, я могу обращаться к документации, а также к конечной точке взаимодействия для взаимодействия.

Я хочу создать отдельную схему для каждого действия viewset. Я пытался написать один, но он не появляется, поэтому я думаю, что что-то упустил.

Вот код:

class Clients(viewsets.ViewSet):

    '''

        Clients is DRF viewset which implements `create`, `update`, `read` actions by implementing create, update, list and retrieve functions respectively.

    '''
    list_schema = schemas.ManualSchema(fields=[
            coreapi.Field(
                'status',
                required=False,
                location='query',
                description='Accepted values are `active`, `inactive`'
            ),          
        ], 
        description='Clients list',
        encoding='application/x-www-form-urlencoded')

    @action(detail=True, schema=list_schema)
    def list(self, request):

        '''Logic for listing'''


    def retrieve(self, request, oid=None):

        '''Logic for retrieval'''


    create_schema = schemas.ManualSchema(fields=[
            coreapi.Field(
                'name',
                required=False,
                location='body',
            ),
            coreapi.Field(
                'location',
                required=False,
                location='body',
            ),              
        ], 
        description='Clients list',
        encoding='application/x-www-form-urlencoded')

    @action(detail=True, schema=create_schema)
    def create(self, request):

        '''Logic for creation'''

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

Так что я отвечу на свой вопрос. Я взглянул на исходный код 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)))

В целях безопасности я не могу поделиться снимками. Извиняюсь за это. Надеюсь, это поможет.

0 голосов
/ 15 ноября 2018

Я думаю, что вы пытаетесь сделать, это невозможно. ViewSet не предоставляет никаких обработчиков методов , следовательно, вы не можете использовать декоратор @action для методов create и list, поскольку они являются существующими маршрутами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...