Настройте свою собственную документацию API для лучшей читаемости

Основываясь на нашем предыдущем руководстве (Плавный переход с Flask на FastAPI), мы собираемся изучить документацию по API сегодня немного подробнее.

К настоящему времени вы должны понимать, что сгенерированная интерактивная документация API и ReDoc для вновь созданного сервера FastAPI не настолько интуитивно понятны и не имеют надлежащих примеров схемы ввода и вывода. Давайте посмотрим на следующие примеры.

Пользовательский интерфейс Swagger:

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

Было бы намного удобнее и понятнее, если бы документация по API выглядела примерно так:

Новому разработчику будет легче читать эту документацию, чем первому.

Переходим к следующему разделу о добавлении метаданных в документацию.

1. Метаданные

Теги

Добавление общих метаданных в документацию можно выполнить непосредственно при инициализации экземпляра FastAPI. Перед этим объявите следующую переменную tags_metadata, которая будет использоваться позже как описание для каждого из имеющихся у нас маршрутов:

tags_metadata содержит список словарей. Каждый словарь должен иметь уникальное имя и состоять из следующих элементов:

  • name - Уникальное имя тега. Настоятельно рекомендуется использовать имя маршрута в качестве имени каждого словаря. Это обязательно по умолчанию.
  • description - Описание тега. Разрешает синтаксис Markdown.
  • externalDocs - Словарь с двумя дополнительными элементами. Первый - description, а второй - url (требуется, если указано externalDocs).

Под описанием вы можете использовать синтаксис Markdown для форматирования текста.

Жирный

Вы должны использовать двойные звездочки для слов, выделенных жирным шрифтом:

The following word is **bolded**.

Курсив

Рекомендуемый синтаксис для курсива - заключить текст в одинарные звездочки:

Flying to *Italy* next week!

Жирный + курсив

Их можно комбинировать следующим образом:

Have a ***great day*** ahead!

Код

Вы можете обозначить код, заключив его в обратные кавычки:

The code snippet is `userName = 'Wai Foong'`

Экземпляр FastAPI

Обычная инициализация экземпляра FastAPI выглядит следующим образом:

app = FastAPI()

Измените его в следующем фрагменте кода:

  • title — представляет заголовок H1, который будет отображаться в верхней части документации.
  • description - Текст описания прямо под заголовком.
  • version - представляет текущую версию вашего API.
  • openapi_tags - Список словарей, содержащих метаданные для каждого из маршрутов. Мы собираемся передать переменную tags_metadata, которую мы определили ранее.

Ярлык

После этого вы можете определить тег внутри маршрута следующим образом:

@app.post("/create-user", tags=["create-user"])
async def create_user(user: User):

Вы должны увидеть описание, отображаемое после обновления веб-страницы по docs URL.

2. Базовая модель Pydantic

Новый класс, унаследованный от BaseModel Pydantic, служит основным элементом процесса проверки в FastAPI. Прочтите Руководство по Pydantic для новичков, чтобы получить дополнительную информацию о фундаментальных концепциях, лежащих в основе этого. Кроме того, любой класс, наследуемый от BaseModel, также служит экземпляром Request Body, в который вы можете добавлять к нему дополнительные метаданные. Обычно вы определяете свои классы следующим образом:

Поле

Чтобы добавить к нему метаданные, вы должны использовать класс Field, который поступает непосредственно из Pydantic. Импортируйте его и измените функцию в следующем фрагменте кода:

Для необязательного аргумента первый параметр должен быть определен как None. Я использую здесь только параметры title и example.

Запрос, тело и путь

Кроме того, вы можете указать тот же аргумент для классов Query, Body и Path. Единственная разница в том, что вам нужно импортировать их из FastAPI вместо Pydantic. Например, учитывая следующий маршрут, который принимает параметр запроса:

@app.get("/get-user", tags=["get-user"])
async def get_user(id: str):

Вы можете легко установить title и example прямо внутри функции маршрута, как показано в примере ниже:

from fastapi import FastAPI, Query
@app.get("/get-user", tags=["get-user"])
async def get_user(id: str = Query(..., title="3-digit identity number of the user", example="010")):

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

Кроме того, будут обновлены примеры для входной полезной нагрузки / схемы:

3. Дополнительные ответы

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

@app.get("/hello", response_class=PlainTextResponse)
async def hello():
    return "Hello World!"

При этом вы можете возвращать разные ответы с дополнительными кодами состояния в своем маршруте. Вы должны вернуть ответ напрямую с кодом состояния - даже если это JSONResponse.

Приведенный ниже фрагмент кода иллюстрирует маршрут, который:

  • Возвращает информацию о пользователе, если найдено совпадение с кодом состояния 200.
  • Возвращает код состояния 404, если совпадения нет.
  • Возвращает код состояния 403, если идентификатор параметра запроса 007 из-за недостаточных прав.

Чтобы включить эту информацию в документацию, вам необходимо изменить два параметра внутри декоратора маршрута:

  • response_model — представляет модель по умолчанию в качестве ответа.
  • responses - Дополнительные ответы в виде словаря, где ключ представляет собой код состояния. Вы можете добавить описание и пример результата, чтобы они появились в документации.

Давайте повторно используем предыдущий фрагмент кода со следующими дополнительными метаданными:

Фактически, вы можете создать словарь предопределенных ответов:

responses = {
    403: {"model": Message, "description": "Insufficient privileges for this action"},
}

И повторно используйте их с помощью метода распаковки Python:

**responses

Не стесняйтесь проверить следующую суть полного кода:

4. Вывод

Подведем итоги тому, что мы узнали сегодня.

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

Затем мы изучили, как добавить метаданные в документацию при инициализации экземпляра FastAPI. Под описанием он имеет отличную поддержку жирного шрифта, курсива и кода, основанного на синтаксисе Markdown.

Мы перешли к следующему разделу, где нам показали правильный способ добавления title и example внутри наших маршрутов. Мы протестировали добавление обеих переменных к нескольким параметрам через классы Field и Query.

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

Спасибо, что прочитали эту статью. Надеюсь увидеть вас снова в следующей статье!

использованная литература

  1. Метаданные и документы FastAPI
  2. Дополнительные ответы FastAPI в OpenAPI
  3. Дополнительная схема FastAPI
  4. Базовый синтаксис руководства по разметке