Схемы

Машиночитаемая [схема] описывает, какие ресурсы доступны через API, каковы их URL, как они представлены и какие операции они поддерживают.

‒ Heroku, JSON Schema for the Heroku Platform API

Схемы API - это полезный инструмент, который позволяет использовать их в различных случаях, включая создание справочной документации или создание динамических клиентских библиотек, которые могут взаимодействовать с вашим API.

Установите Core API и PyYAML

Вам необходимо установить пакет coreapi, чтобы добавить поддержку схем для REST framework. Возможно, вы также захотите установить пакет pyyaml , чтобы вы могли преобразовать схему в широко используемый формат OpenAPI, основанный на YAML.

pip install coreapi pyyaml

Быстрый старт

Существует два различных способа предоставления описания схемы для вашего API.

Генерация схемы с помощью команды управления generateschema

Чтобы создать статическую схему API, используйте команду управления generateschema.

$ python manage.py generateschema > schema.yml

После создания схемы таким образом вы можете аннотировать ее любой дополнительной информацией, которая не может быть автоматически выведена генератором схемы.

Вы можете зарегистрировать схему API в системе контроля версий и обновлять ее с каждым новым релизом, или использовать схему API из статического медиа вашего сайта.

Добавление представления с get_schema_view

Чтобы добавить динамически создаваемое представление схемы в ваш API, используйте get_schema_view.

from rest_framework.schemas import get_schema_view
from django.urls import path

schema_view = get_schema_view(title="Example API")

urlpatterns = [
    path('schema', schema_view),
    ...
]

Смотрите ниже for more details о настройке динамически генерируемого представления схемы.

Внутреннее представление схемы

Фреймворк REST использует Core API для моделирования информации схемы в независимом от формата представлении. Затем эта информация может быть преобразована в различные форматы схем или использована для создания документации API.

При использовании Core API схема представлена в виде Document, который является объектом-контейнером верхнего уровня для информации об API. Доступные взаимодействия API представлены с помощью объектов Link. Каждая ссылка включает URL, метод HTTP и может включать список экземпляров Field, которые описывают любые параметры, которые могут быть приняты конечной точкой API. Экземпляры Link и Field могут также включать описания, которые позволяют преобразовать схему API в пользовательскую документацию.

Вот пример описания API, включающего единственную конечную точку search:

coreapi.Document(
    title='Flight Search API',
    url='https://api.example.org/',
    content={
        'search': coreapi.Link(
            url='/search/',
            action='get',
            fields=[
                coreapi.Field(
                    name='from',
                    required=True,
                    location='query',
                    description='City name or airport code.'
                ),
                coreapi.Field(
                    name='to',
                    required=True,
                    location='query',
                    description='City name or airport code.'
                ),
                coreapi.Field(
                    name='date',
                    required=True,
                    location='query',
                    description='Flight date in "YYYY-MM-DD" format.'
                )
            ],
            description='Return flight availability and prices.'
        )
    }
)

Форматы вывода схем

Чтобы быть представленным в HTTP-ответе, внутреннее представление должно быть преобразовано в фактические байты, которые используются в ответе.

REST framework включает несколько различных рендерингов, которые можно использовать для кодирования схемы API.

  • renderers.OpenAPIRenderer - Рендеринг в формат схемы API на основе YAML :doc:`OpenAPI <https://openapis.org/>`** , наиболее широко используемый формат схемы API.

  • renderers.JSONOpenAPIRenderer - Рендеринг в JSON на основе OpenAPI.

  • renderers.CoreJSONRenderer - Рендеринг в Core JSON <https://www.coreapi.org/specification/encoding/#core-json-encoding>`** , формат, разработанный для использования с клиентской библиотекой ``coreapi`.

Core JSON разработан как канонический формат для использования с Core API. REST framework включает класс рендерера для работы с этим типом медиа, который доступен как renderers.CoreJSONRenderer.

Схемы против гипермедиа

Здесь стоит отметить, что Core API также можно использовать для моделирования гипермедийных ответов, которые представляют собой альтернативный стиль взаимодействия со схемами API.

При использовании схемы API весь доступный интерфейс представляется заранее в виде одной конечной точки. Ответы на отдельные конечные точки API обычно представляются как обычные данные, без каких-либо дополнительных взаимодействий, содержащихся в каждом ответе.

При использовании гипермедиа клиент получает документ, содержащий как данные, так и доступные взаимодействия. Каждое взаимодействие приводит к созданию нового документа, в котором подробно описывается как текущее состояние, так и доступные взаимодействия.

Дополнительная информация и поддержка по созданию гипермедийных API с помощью REST-фреймворка запланирована на будущую версию.


Создание схемы

REST-фреймворк включает функциональность для автоматической генерации схемы или позволяет указать ее в явном виде.

Спецификация схемы вручную

Чтобы вручную указать схему, вы создаете Core API Document , аналогично приведенному выше примеру.

schema = coreapi.Document(
    title='Flight Search API',
    content={
        ...
    }
)

Автоматическая генерация схем

Автоматическая генерация схемы обеспечивается классом SchemaGenerator.

SchemaGenerator обрабатывает список маршрутизируемых шаблонов URL и составляет соответствующим образом структурированный документ Core API.

Базовое использование - просто дать название вашей схеме и вызвать get_schema() :

generator = schemas.SchemaGenerator(title='Flight Search API')
schema = generator.get_schema()

Настройка схемы для каждого вида

По умолчанию интроспекция представления выполняется экземпляром AutoSchema, доступным через атрибут schema на APIView. Он предоставляет соответствующий объект Core API Link для представления, метода запроса и пути:

auto_schema = view.schema
coreapi_link = auto_schema.get_link(...)

(При компиляции схемы SchemaGenerator вызывает view.schema.get_link() для каждого представления, разрешенного метода и пути).


Примечание : Для базовых подклассов APIView по умолчанию интроспекция ограничивается параметрами пути URL kwarg. Для GenericAPIView подклассов, которые включают все предоставленные представления, основанные на классах, AutoSchema будет пытаться проанализировать поля сериализатора, пагинации и фильтра, а также предоставить более богатые описания полей пути. (Ключевыми крючками здесь являются соответствующие GenericAPIView атрибуты и методы: get_serializer , pagination_class , filter_backends и так далее).


Чтобы настроить генерацию Link, вы можете:

  • Инстанцируйте AutoSchema на вашем представлении с помощью карги manual_fields:

       from rest_framework.views import APIView
       from rest_framework.schemas import AutoSchema
    
       class CustomView(APIView):
           ...
           schema = AutoSchema(
               manual_fields=[
                   coreapi.Field("extra_field", ...),
               ]
           )
    
    
    This allows extension for the most common case without subclassing.
    
  • Предоставьте подкласс AutoSchema с более сложной настройкой:

       from rest_framework.views import APIView
       from rest_framework.schemas import AutoSchema
    
       class CustomSchema(AutoSchema):
           def get_link(...):
               # Implement custom introspection here (or in other sub-methods)
    
       class CustomView(APIView):
           ...
           schema = CustomSchema()
    
    
    This provides complete control over view introspection.
    
  • Инстанцируйте ManualSchema на вашем представлении, явно предоставляя Core API Fields для представления:

       from rest_framework.views import APIView
       from rest_framework.schemas import ManualSchema
    
       class CustomView(APIView):
           ...
           schema = ManualSchema(fields=[
               coreapi.Field(
                   "first_field",
                   required=True,
                   location="path",
                   schema=coreschema.String()
               ),
               coreapi.Field(
                   "second_field",
                   required=True,
                   location="path",
                   schema=coreschema.String()
               ),
           ])
    
    
    This allows manually specifying the schema for some views whilst maintaining
    automatic generation elsewhere.
    

Вы можете отключить генерацию схемы для представления, установив schema в None :

class CustomView(APIView):
    ...
    schema = None  # Will not appear in schema

Это также относится к дополнительным действиям для ViewSet s:

class CustomViewSet(viewsets.ModelViewSet):

    @action(detail=True, schema=None)
    def extra_action(self, request, pk=None):
        ...

Примечание : Для получения полной информации о SchemaGenerator плюс дескрипторы AutoSchema и ManualSchema смотрите API Reference below.


Добавление представления схемы

Существует несколько различных способов добавить представление схемы в ваш API, в зависимости от того, что именно вам нужно.

Ярлык get_schema_view

Самый простой способ включить схему в проект - использовать функцию get_schema_view().

from rest_framework.schemas import get_schema_view

schema_view = get_schema_view(title="Server Monitoring API")

urlpatterns = [
    path('', schema_view),
    ...
]

После добавления представления вы сможете делать API-запросы для получения автоматически сгенерированного определения схемы.

$ http http://127.0.0.1:8000/ Accept:application/coreapi+json
HTTP/1.0 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/vnd.coreapi+json

{
    "_meta": {
        "title": "Server Monitoring API"
    },
    "_type": "document",
    ...
}

Аргументами для get_schema_view() являются:

Может использоваться для предоставления описательного заголовка для определения схемы.

Может использоваться для передачи канонического URL для схемы.

schema_view = get_schema_view(
    title='Server Monitoring API',
    url='https://www.example.org/api/'
)

Строка, представляющая путь импорта к URL conf, для которого вы хотите сгенерировать схему API. По умолчанию это значение соответствует значению параметра ROOT_URLCONF в Django.

schema_view = get_schema_view(
    title='Server Monitoring API',
    url='https://www.example.org/api/',
    urlconf='myproject.urls'
)

Может использоваться для передачи набора классов рендеринга, которые могут быть использованы для рендеринга корневой конечной точки API.

from rest_framework.schemas import get_schema_view
from rest_framework.renderers import JSONOpenAPIRenderer

schema_view = get_schema_view(
    title='Server Monitoring API',
    url='https://www.example.org/api/',
    renderer_classes=[JSONOpenAPIRenderer]
)

Список шаблонов url для ограничения интроспекции схемы. Если вы хотите, чтобы только myproject.api урлы были отображены в схеме:

schema_url_patterns = [
    path('api/', include('myproject.api.urls')),
]

schema_view = get_schema_view(
    title='Server Monitoring API',
    url='https://www.example.org/api/',
    patterns=schema_url_patterns,
)

Может использоваться для указания подкласса SchemaGenerator, который будет передан в SchemaView.

Может использоваться для указания списка классов аутентификации, которые будут применяться к конечной точке схемы. По умолчанию settings.DEFAULT_AUTHENTICATION_CLASSES

Может использоваться для указания списка классов разрешений, которые будут применяться к конечной точке схемы. По умолчанию settings.DEFAULT_PERMISSION_CLASSES.

Использование явного представления схемы

Если вам нужно немного больше контроля, чем дает ярлык get_schema_view(), то вы можете использовать класс SchemaGenerator непосредственно для автоматической генерации экземпляра Document и возврата его из представления.

Эта опция дает вам гибкость в настройке конечной точки схемы с любым поведением, которое вы хотите. Например, вы можете применить к конечной точке схемы различные политики разрешений, дросселирования или аутентификации.

Вот пример использования SchemaGenerator вместе с представлением для возврата схемы.

views.py:

from rest_framework.decorators import api_view, renderer_classes
from rest_framework import renderers, response, schemas

generator = schemas.SchemaGenerator(title='Bookings API')

@api_view()
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
    schema = generator.get_schema(request)
    return response.Response(schema)

urls.py:

urlpatterns = [
    path('', schema_view),
    ...
]

Вы также можете предоставлять разные схемы разным пользователям в зависимости от имеющихся у них прав. Этот подход можно использовать для того, чтобы неаутентифицированные запросы получали схему, отличную от схемы аутентифицированных запросов, или для того, чтобы разные части API были видны разным пользователям в зависимости от их роли.

Для того чтобы представить схему с конечными точками, отфильтрованными по разрешениям пользователя, необходимо передать аргумент request в метод get_schema(), как показано ниже:

@api_view()
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
    generator = schemas.SchemaGenerator(title='Bookings API')
    return response.Response(generator.get_schema(request=request))

Явное определение схемы

Альтернативой автоматически генерируемому подходу является явное определение схемы API путем объявления объекта Document в вашей кодовой базе. Это немного больше работы, но гарантирует, что у вас есть полный контроль над представлением схемы.

import coreapi
from rest_framework.decorators import api_view, renderer_classes
from rest_framework import renderers, response

schema = coreapi.Document(
    title='Bookings API',
    content={
        ...
    }
)

@api_view()
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
    return response.Response(schema)

Схемы как документация

Одно из распространенных применений схем API - это использование их для создания страниц документации.

Генерация схемы в REST framework использует docstrings для автоматического заполнения описаний в документе схемы.

Эти описания будут основаны на:

  • Соответствующая doc-строка метода, если таковая существует.

  • Именованный раздел в строке документа класса, который может быть как однострочным, так и многострочным.

  • Докстрока класса.

Примеры

APIView , с явным методом docstring.

class ListUsernames(APIView):
    def get(self, request):
        """
        Return a list of all user names in the system.
        """
        usernames = [user.username for user in User.objects.all()]
        return Response(usernames)

A ViewSet , с явным действием docstring.

class ListUsernames(ViewSet):
    def list(self, request):
        """
        Return a list of all user names in the system.
        """
        usernames = [user.username for user in User.objects.all()]
        return Response(usernames)

Общий вид с разделами в классе docstring, с использованием однострочного стиля.

class UserList(generics.ListCreateAPIView):
    """
    get: List all the users.
    post: Create a new user.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAdminUser]

Общий набор представлений с разделами в классе docstring, использующий многострочный стиль.

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.

    retrieve:
    Return a user instance.

    list:
    Return all users, ordered by most recently joined.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

Справочник по API

SchemaGenerator

Класс, который просматривает список шаблонов URL, запрашивает схему для каждого представления и собирает результирующий документ CoreAPI.

Обычно вы создаете SchemaGenerator с одним аргументом, например, так:

generator = SchemaGenerator(title='Stock Prices API')

Аргументы:

  • title обязательно - Имя API.

  • url - Корневой URL схемы API. Этот параметр не требуется, если схема не включена в префикс path.

  • patterns - Список URL-адресов для проверки при генерации схемы. По умолчанию используется URL conf проекта.

  • urlconf - Имя модуля URL conf для использования при генерации схемы. По умолчанию settings.ROOT_URLCONF.

get_schema(self, request)

Возвращает экземпляр coreapi.Document, представляющий схему API.

@api_view
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
    generator = schemas.SchemaGenerator(title='Bookings API')
    return Response(generator.get_schema())

Аргумент request является необязательным и может быть использован, если вы хотите применить разрешения для каждого пользователя к результирующей генерации схемы.

AutoSchema

Класс, который занимается интроспекцией отдельных представлений для генерации схемы.

AutoSchema присоединяется к APIView через атрибут schema.

Конструктор AutoSchema принимает единственный аргумент в виде ключевого слова manual_fields.

** manual_fields ** : list из coreapi.Field экземпляров, которые будут добавлены к сгенерированным полям. Сгенерированные поля с совпадающим name будут перезаписаны.

class CustomView(APIView):
    schema = AutoSchema(manual_fields=[
        coreapi.Field(
            "my_extra_field",
            required=True,
            location="path",
            schema=coreschema.String()
        ),
    ])

Для более продвинутой настройки подкласс AutoSchema для настройки генерации схемы.

class CustomViewSchema(AutoSchema):
    """
    Overrides `get_link()` to provide Custom Behavior X
    """

    def get_link(self, path, method, base_url):
        link = super().get_link(path, method, base_url)
        # Do something to customize link here...
        return link

class MyView(APIView):
  schema = CustomViewSchema()

Для переопределения доступны следующие методы.

get_description(self, path, method)

Возвращает строку для использования в качестве описания ссылки. По умолчанию она основывается на docstring представления, как описано в разделе «Схемы как документация» выше.

get_encoding(self, path, method)

Возвращает строку, указывающую кодировку для любого тела запроса при взаимодействии с данным представлением. Например, 'application/json'. Может возвращать пустую строку для представлений, которые не ожидают тело запроса.

get_path_fields(self, path, method):

Возвращает список экземпляров coreapi.Field(). По одному для каждого параметра пути в URL.

get_serializer_fields(self, path, method)

Возвращает список экземпляров coreapi.Field(). По одному для каждого поля в классе сериализатора, используемого представлением.

get_pagination_fields(self, path, method)

Возвращает список экземпляров coreapi.Field(), возвращенных методом get_schema_fields() любого класса пагинации, используемого представлением.

get_filter_fields(self, path, method)

Возвращает список coreapi.Field() экземпляров, возвращенных методом get_schema_fields() любых классов фильтров, используемых представлением.

get_manual_fields(self, path, method)

Возвращает список coreapi.Field() экземпляров, которые будут добавлены к сгенерированным полям или заменят их. По умолчанию равен (необязательному) manual_fields, переданному в AutoSchema конструктор.

Может быть переопределена для настройки ручных полей на path или method. Например, настройка для каждого метода может выглядеть следующим образом:

def get_manual_fields(self, path, method):
    """Example adding per-method fields."""

    extra_fields = []
    if method=='GET':
        extra_fields = # ... list of extra fields for GET ...
    if method=='POST':
        extra_fields = # ... list of extra fields for POST ...

    manual_fields = super().get_manual_fields(path, method)
    return manual_fields + extra_fields

update_fields(fields, update_with)

Утилита staticmethod. Инкапсулирует логику добавления или замены полей из списка на Field.name. Может быть переопределена для настройки критериев замены.

ManualSchema

Позволяет вручную предоставить список coreapi.Field экземпляров для схемы, плюс необязательное описание.

class MyView(APIView):
  schema = ManualSchema(fields=[
        coreapi.Field(
            "first_field",
            required=True,
            location="path",
            schema=coreschema.String()
        ),
        coreapi.Field(
            "second_field",
            required=True,
            location="path",
            schema=coreschema.String()
        ),
    ]
  )

Конструктор ManualSchema принимает два аргумента:

** fields ** : Список coreapi.Field экземпляров. Требуется.

** description ** : Строковое описание. Необязательно.

** encoding ** : По умолчанию None. Кодировка строки, например, application/json. Необязательно.


Основной API

Эта документация дает краткий обзор компонентов пакета coreapi, которые используются для представления схемы API.

Обратите внимание, что эти классы импортируются из пакета coreapi, а не из пакета rest_framework.

Документ

Представляет собой контейнер для схемы API.

title

Имя для API.

url

Канонический URL для API.

content

Словарь, содержащий Link объектов, которые содержит схема.

Для того чтобы обеспечить большую структуру схемы, словарь content может быть вложенным, обычно до второго уровня. Например:

content={
    "bookings": {
        "list": Link(...),
        "create": Link(...),
        ...
    },
    "venues": {
        "list": Link(...),
        ...
    },
    ...
}

Поле

Представляет один входной параметр на данной конечной точке API.

name

Описательное имя для входа.

required

Булево значение, указывающее, должен ли клиент включить значение, или параметр может быть опущен.

location

Определяет, как информация будет закодирована в запросе. Должна быть одной из следующих строк:

«путь «

Включено в шаблонный URI. Например, значение url /products/{product_code}/ может быть использовано вместе с полем "path" для обработки входов API в пути URL, например /products/slim-fit-jeans/.

Эти поля обычно соответствуют named arguments in the project URL conf.

«запрос «

Включается в качестве параметра запроса URL. Например, ?search=sale. Обычно для запросов GET.

Эти поля обычно соответствуют элементам управления пагинацией и фильтрацией в представлении.

«форма «

Включается в тело запроса, как отдельный элемент объекта JSON или HTML-формы. Например, {"colour": "blue", ...}. Обычно для запросов POST , PUT и PATCH. Несколько полей "form" могут быть включены в одну ссылку.

Эти поля обычно соответствуют полям сериализатора в представлении.

«тело «

Включается как полное тело запроса. Обычно для запросов POST , PUT и PATCH. В ссылке может существовать не более одного поля "body". Не может использоваться вместе с полями "form".

Эти поля обычно соответствуют представлениям, которые используют ListSerializer для проверки ввода запроса, или представлениям загрузки файлов.

encoding

«application/json «.

Содержимое запроса в кодировке JSON. Соответствует представлениям, использующим JSONParser. Действителен только в том случае, если в location="form" включено одно или несколько полей location="body" или одно поле Link.

«multipart/form-data «.

Многочастное кодированное содержимое запроса. Соответствует представлениям, использующим MultiPartParser. Действителен, только если одно или более полей location="form" включено в Link.

** «application/x-www-form-urlencoded «**.

URL-кодированное содержимое запроса. Соответствует представлениям, использующим FormParser. Действителен, только если одно или более полей location="form" включено в Link.

«application/octet-stream «.

Содержание запроса на бинарную загрузку. Соответствует представлениям, использующим FileUploadParser. Действителен только в том случае, если поле location="body" включено в Link.

description

Краткое описание значения и предполагаемого использования поля ввода.


Пакеты сторонних производителей

drf-yasg - Еще один генератор Swagger

drf-yasg генерирует OpenAPI документы, пригодные для генерации кода - вложенные схемы, именованные модели, тела ответов, валидаторы enum/pattern/min/max, параметры форм и т.д.

drf-spectacular - Разумная и гибкая генерация схем OpenAPI 3.0 для REST-фреймворка Django

drf-spectacular - это инструмент генерации схем OpenAPI 3 с явным акцентом на расширяемость, настраиваемость и генерацию клиентов. Модели его использования очень похожи на drf-yasg.

Вернуться на верх