Настройте свою собственную документацию 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
.
Более того, мы также узнали о возврате дополнительных ответов непосредственно с кодом состояния. Дополнительная информация может быть указана внутри декоратора маршрута, чтобы она появилась в документации.
Спасибо, что прочитали эту статью. Надеюсь увидеть вас снова в следующей статье!