Python
November 2

FastAPI: подробное руководство по основным сущностям

FastAPI — это мощный и интуитивно понятный фреймворк для создания современных веб-API на Python, который завоевал популярность среди разработчиков благодаря своей скорости, удобству и гибкости. Он позволяет легко создавать надёжные и масштабируемые API, автоматически проверять данные и генерировать удобную документацию. Одним из ключевых преимуществ FastAPI является простота работы с различными типами данных и параметрами, что делает фреймворк подходящим как для небольших, так и для крупных проектов.

Мы уже ознакомились с базовыми принципами FastAPI тут: FastAPI для начинающих: простое руководство по созданию быстрых API, а в этом руководстве мы подробно разберём основные сущности FastAPI, которые делают разработку API удобной и предсказуемой. Мы охватим:

  • Path Parameters (Параметры пути): доступ к ресурсам через значения, передаваемые в URL.
  • Query Parameters (Параметры запроса): фильтрация и обработка данных через параметры, передаваемые после ?.
  • Request Body (Тело запроса): передача данных в формате JSON для взаимодействия с API.
  • Validation (Валидация): использование встроенной валидации для строковых и числовых параметров.
  • Nested Models (Вложенные модели): создание сложных JSON-структур с помощью вложенных моделей.
  • Header Parameters и Cookie Parameters (Параметры заголовков и cookies): извлечение и использование данных из заголовков и cookies для настройки запросов.
  • Response Models (Модели ответа): использование моделей для структурирования и проверки ответа.
  • Form Data и File Uploads (Данные форм и загрузка файлов): работа с формами и обработка загружаемых файлов.
  • Handling Errors (Обработка ошибок): создание кастомных ошибок для более информативных ответов.
  • Path Operation Configuration (Конфигурация операций маршрута): добавление тегов, описаний и статусов ответов для улучшения документации и структуры API.

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

Присоединяйтесь к нам в этом путешествии по FastAPI и убедитесь, что создание API может быть лёгким и увлекательным! 🐱

Часть 1: Параметры пути и запроса в FastAPI

FastAPI делает работу с параметрами API удобной и безопасной. Вы можете передавать данные через URL, используя параметры пути или параметры запроса, и получать доступ к этим данным в обработчиках. В этой части мы разберём, как использовать Path Parameters и Query Parameters в FastAPI.


1. Path Parameters (Параметры пути)

Path Parameters (Параметры пути) — это значения, которые передаются непосредственно в URL. Они используются для доступа к конкретным ресурсам и обычно являются обязательными. FastAPI позволяет удобно и безопасно получать значения этих параметров и автоматически проводить валидацию типов данных.

Пример

В следующем примере мы создадим маршрут /items/{item_id}, где item_id — это параметр пути, представляющий идентификатор элемента.

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}

Объяснение кода

  • В функции read_item параметр item_id автоматически извлекается из URL и приводится к целому числу (int).
  • Если клиент отправляет запрос GET /items/5, FastAPI интерпретирует 5 как значение для item_id и возвращает его в виде JSON.

Преимущества Path Parameters

  • Простота доступа: вы можете получать данные непосредственно из URL.
  • Валидация типов данных: FastAPI автоматически проверит, что item_id является числом, и вернёт ошибку, если это не так.

Path Parameters особенно полезны для доступа к отдельным ресурсам, например, к товарам по их ID или пользователям по их уникальному идентификатору.

2. Query Parameters (Параметры запроса)

Query Parameters (Параметры запроса) передаются после символа ? в URL. Они обычно используются для передачи дополнительных параметров, которые могут быть необязательными, и их можно комбинировать для настройки вывода, фильтрации или пагинации.

Пример

В следующем примере мы добавим маршрут /items/, который принимает параметры skip и limit. Эти параметры полезны для реализации пагинации (например, пропуска первых элементов и ограничения количества).

@app.get("/items/")
def read_items(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

Объяснение кода

  • skip и limit — это необязательные параметры запроса с заданными значениями по умолчанию (0 и 10 соответственно).
  • При отправке запроса GET /items?skip=5&limit=20 FastAPI автоматически присвоит skip=5 и limit=20.

Преимущества Query Parameters

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

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

Часть 2: Работа с телом запроса и валидацией в FastAPI

В этой части мы рассмотрим, как передавать данные через Request Body (Тело запроса) и использовать встроенные возможности валидации FastAPI для работы со строками и числами. Мы также разберём, как использовать модели данных, чтобы сделать код более структурированным и безопасным.

3. Request Body (Тело запроса)

Request Body — это основная часть запроса, которая используется для передачи данных в формате JSON. В FastAPI для описания и валидации структуры данных, отправляемых в теле запроса, удобно использовать модели данных Pydantic. Это позволяет автоматически проверять данные и создавать документацию API.

Пример

Допустим, мы создаём API для управления товарами. Мы определим модель Item, которая описывает структуру товара, и будем использовать её для получения данных в теле запроса.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float

@app.post("/items/")
def create_item(item: Item):
    return {"name": item.name, "price": item.price}

Объяснение кода

  • Модель Item, унаследованная от BaseModel, содержит два поля: name и price.
  • Когда клиент отправляет запрос POST /items/ с JSON-данными, FastAPI автоматически преобразует их в объект Item.
  • Данные проверяются на соответствие типам (name — строка, price — число с плавающей точкой), и в случае несоответствия клиенту будет возвращена ошибка.

Преимущества использования Request Body и моделей

  • Автоматическая валидация данных: FastAPI проверит соответствие типов данных, определённых в модели.
  • Чистый и понятный код: модели помогают структурировать код и избегать ошибок при обработке данных.

4. Query Parameters and String Validations (Параметры запроса и валидация строк)

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

Пример

В следующем примере мы добавим параметр запроса q, который должен быть строкой с минимальной длиной 3 символа и максимальной длиной 50 символов.

from fastapi import Query

@app.get("/items/")
def read_items(q: str = Query(..., min_length=3, max_length=50)):
    return {"q": q}

Объяснение кода

  • Параметр q передаётся через запрос, и с помощью Query мы указываем минимальную и максимальную длину строки.
  • Значение ... указывает, что параметр q является обязательным.
  • Если длина строки не соответствует требованиям, FastAPI вернёт сообщение об ошибке.

Дополнительные возможности валидации строк

Кроме длины строки, Query позволяет задать регулярные выражения для валидации:

@app.get("/items/")
def read_items(q: str = Query(..., regex="^fixed_")):
    return {"q": q}

Здесь q должно начинаться с префикса "fixed_", и запросы, которые не соответствуют этому шаблону, вызовут ошибку.

5. Path Parameters and Numeric Validations (Параметры пути и числовая валидация)

FastAPI также поддерживает валидацию числовых значений для Path Parameters. Это полезно для ограничения допустимых значений и обеспечения корректности данных.

Пример

В следующем примере мы зададим ограничение для параметра item_id, который должен быть числом от 1 до 100.

from fastapi import Path

@app.get("/items/{item_id}")
def read_item(item_id: int = Path(..., ge=1, le=100)):
    return {"item_id": item_id}

Объяснение кода

  • item_id — это числовой параметр пути, который должен быть не меньше 1 (ge=1) и не больше 100 (le=100).
  • FastAPI проверит, что значение находится в допустимом диапазоне, и вернёт ошибку, если это не так.

Преимущества числовой валидации Path Parameters

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

Часть 3: Модели параметров запроса и тела запроса

В этой части мы разберём более сложные возможности FastAPI, такие как использование Query Parameter Models (Модели параметров запроса) и Body - Multiple Parameters (Тело запроса - Несколько параметров). Эти инструменты позволяют структурировать код и управлять данными запросов более гибко.

6. Query Parameter Models (Модели параметров запроса)

Для сложных запросов, которые содержат несколько параметров, FastAPI позволяет использовать модели Pydantic, чтобы сделать код более структурированным и удобным для поддержки. Модель параметров запроса упрощает передачу нескольких параметров и позволяет добавлять валидацию.

Пример

В этом примере мы создадим модель FilterParams, которая включает параметры q и limit. Эта модель будет использоваться как зависимость в маршруте.

from fastapi import Depends
from pydantic import BaseModel

class FilterParams(BaseModel):
    q: str
    limit: int = 10

@app.get("/items/")
def read_items(filters: FilterParams = Depends()):
    return filters

Объяснение кода

  • FilterParams — это модель Pydantic, описывающая структуру параметров запроса с полями q и limit.
  • Depends() позволяет передать объект FilterParams как зависимость. FastAPI автоматически создаст экземпляр этой модели и проверит параметры запроса, если они присутствуют.

Преимущества использования моделей параметров запроса

  • Чистота кода: использование модели помогает избежать большого количества параметров в функции.
  • Автоматическая валидация: параметры будут автоматически проверены на соответствие типам.
  • Удобство использования в документации: FastAPI автоматически генерирует документацию для модели.

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

7. Body - Multiple Parameters (Тело запроса - Несколько параметров)

FastAPI позволяет передавать несколько параметров через тело запроса и объединять их с параметрами пути и запроса. Это полезно для обработки сложных запросов, в которых сочетаются разные типы данных.

Пример

В этом примере мы создаём маршрут, который принимает item_id как Path Parameter, а также name и price как параметры тела запроса.

from fastapi import Body

@app.put("/items/{item_id}")
def update_item(item_id: int, name: str = Body(...), price: float = Body(...)):
    return {"item_id": item_id, "name": name, "price": price}

Объяснение кода

  • Параметр item_id передаётся через путь, а name и price — через тело запроса.
  • Body(...) указывает FastAPI, что эти параметры находятся в теле запроса и являются обязательными.

Преимущества использования нескольких параметров тела

  • Гибкость: можно комбинировать данные из разных источников (путь, тело, параметры запроса).
  • Чистота кода: параметры, определённые через Body, остаются структурированными и удобными для чтения.

8. Body - Fields (Поля тела запроса)

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

Пример

В следующем примере мы определим модель Item, добавив к полям name и price условия валидации и описание.

from pydantic import BaseModel, Field

class Item(BaseModel):
    name: str = Field(..., title="Name of the item", min_length=3, max_length=50)
    price: float = Field(..., gt=0, description="Price must be greater than zero")

@app.post("/items/")
def create_item(item: Item):
    return item

Объяснение кода

  • Поле name имеет ограничения по длине строки (от 3 до 50 символов), а также заголовок (title) для улучшения документации.
  • Поле price проверяется на положительное значение (должно быть больше 0) и снабжено описанием (description).

Преимущества использования Field

  • Дополнительная валидация: позволяет задать более точные условия для каждого поля.
  • Документация: FastAPI автоматически добавляет описания и ограничения в документацию API.

9. Body - Nested Models (Вложенные модели в теле запроса)

FastAPI поддерживает вложенные структуры данных, что удобно для создания сложных JSON-объектов. Вложенные модели помогают организовать данные и повысить читаемость кода.

Пример

В этом примере мы создадим модель Owner, которая будет вложена в модель Item, чтобы описать структуру владельца товара.

class Owner(BaseModel):
    name: str
    age: int

class Item(BaseModel):
    name: str
    price: float
    owner: Owner

@app.post("/items/")
def create_item(item: Item):
    return item

Объяснение кода

  • Owner — это отдельная модель, описывающая владельца товара.
  • Item включает поле owner, которое является экземпляром модели Owner.

Преимущества использования вложенных моделей

  • Организация данных: позволяет создавать сложные JSON-структуры с вложенными объектами.
  • Автоматическая валидация всех уровней: FastAPI проверяет как основную модель, так и вложенные модели.
  • Удобная работа с данными: вложенные модели делают код более читаемым и логичным.

Часть 4: Примеры данных, дополнительные типы данных и работа с cookies и заголовками

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

10. Declare Request Example Data (Объявление примеров данных запроса)

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

Пример

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

from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float

    class Config:
        schema_extra = {
            "example": {
                "name": "Sample Item",
                "price": 19.99
            }
        }

Объяснение кода

  • schema_extra в Config позволяет задать пример данных.
  • Этот пример отображается в документации /docs и показывает ожидаемую структуру и значения.

Преимущества объявления примеров данных

  • Улучшение документации: примеры делают документацию более наглядной.
  • Удобство для разработчиков: показывает формат и структуру данных, упрощая использование API.

11. Extra Data Types (Дополнительные типы данных)

FastAPI поддерживает дополнительные типы данных, такие как datetime, UUID, Decimal и другие, что позволяет более точно описывать данные и автоматизировать их проверку.

Пример

В этом примере мы добавим параметры типа datetime и UUID к модели Event, чтобы описать событие с точной датой и уникальным идентификатором.

from datetime import datetime
from uuid import UUID
from pydantic import BaseModel

class Event(BaseModel):
    id: UUID
    timestamp: datetime
    name: str

Объяснение кода

  • UUID используется для создания уникальных идентификаторов.
  • datetime позволяет задавать временные метки.

Преимущества использования дополнительных типов данных

  • Точность данных: позволяет точнее описывать структуры и уменьшает вероятность ошибок.
  • Автоматическая валидация: FastAPI автоматически проверяет формат данных, таких как datetime и UUID.

12. Cookie Parameters (Параметры cookies)

Cookies часто используются для хранения данных на стороне клиента, таких как сессии и настройки пользователя. FastAPI позволяет получать значения cookies в эндпоинтах с помощью Cookie.

Пример использования

В этом примере мы используем параметр session_id, чтобы прочитать его из cookies.

from fastapi import Cookie

@app.get("/items/")
def read_items(session_id: str = Cookie(None)):
    return {"session_id": session_id}

Объяснение кода

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

Преимущества использования Cookie Parameters

  • Работа с сессиями: удобный способ отслеживать пользователей и их состояние.
  • Простота валидации: FastAPI автоматически обрабатывает и проверяет cookies.

13. Header Parameters (Параметры заголовка)

Заголовки HTTP часто содержат полезную информацию, такую как User-Agent, токены аутентификации и другую служебную информацию. FastAPI позволяет получать значения заголовков с помощью Header.

Пример использования

В этом примере мы извлекаем значение заголовка User-Agent для анализа информации о клиенте.

from fastapi import Header

@app.get("/items/")
def read_items(user_agent: str = Header(None)):
    return {"User-Agent": user_agent}

Объяснение кода

  • user_agent передаётся в обработчик как параметр Header.
  • FastAPI автоматически извлекает заголовок User-Agent и передаёт его в функцию.

Преимущества использования Header Parameters

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

Часть 5: Модели ответа, статусные коды, данные форм и загрузка файлов

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

14. Response Model - Return Type (Модель ответа - Тип возвращаемого значения)

FastAPI позволяет описывать структуру ответа с помощью моделей Pydantic, что помогает явно указать, какие данные возвращаются из эндпоинта. Модели ответа также позволяют автоматически валидировать и форматировать данные перед отправкой клиенту.

Пример

В этом примере мы создадим модель Item, которая будет использоваться как ответ на запрос.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float

@app.get("/items/{item_id}", response_model=Item)
def read_item(item_id: int):
    return Item(name="Sample Item", price=20.0)

Объяснение кода

  • Модель Item описывает структуру данных, возвращаемую из эндпоинта.
  • Параметр response_model=Item указывает FastAPI использовать эту модель для валидации и форматирования ответа.

Преимущества использования моделей ответа

  • Единая структура ответов: позволяет клиентам легко понять формат данных.
  • Автоматическая валидация: FastAPI проверяет соответствие возвращаемых данных модели, предотвращая непредвиденные ошибки.

15. Response Status Code (Код состояния ответа)

FastAPI позволяет указывать статусные коды HTTP для эндпоинтов. Это полезно для обозначения успешности или ошибки запроса. Например, для создания ресурса можно использовать код 201 Created.

Пример

В следующем примере мы укажем статусный код 201 для эндпоинта, который создаёт элемент.

from fastapi import status

@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
def create_item(item: Item):
    return item

Объяснение кода

  • status_code=status.HTTP_201_CREATED указывает, что запрос завершился успешно и новый ресурс был создан.
  • FastAPI автоматически добавит этот статусный код в ответ.

Преимущества использования статусных кодов

  • Информативность: клиенты получают точные статусы ответов и могут обрабатывать их соответствующим образом.
  • Лучшая совместимость с REST: использование правильных кодов делает API более предсказуемым и стандартизированным.

16. Form Data (Формы с данными)

FastAPI позволяет передавать данные в формате форм, что полезно для работы с HTML-формами или другими клиентами, которые используют кодировку application/x-www-form-urlencoded. Для работы с данными формы используется класс Form.

Пример использования

В этом примере мы создадим эндпоинт для обработки формы входа с полями username и password.

from fastapi import Form

@app.post("/login/")
def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username}

Объяснение кода

  • Form(...) указывает, что данные будут получены из формы.
  • Поля username и password обязательны, так как ... (три точки) обозначают отсутствие значения по умолчанию.

Преимущества использования Form Data

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

17. Form Models (Модели форм)

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

Пример использования

В этом примере мы создаём модель LoginForm, чтобы описать структуру данных для формы входа.

from pydantic import BaseModel

class LoginForm(BaseModel):
    username: str
    password: str

@app.post("/login/")
def login(form_data: LoginForm = Depends()):
    return {"username": form_data.username}

18. Request Files (Файлы в запросаз)

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

Пример использования

В этом примере мы создаём эндпоинт, который принимает файл и возвращает его имя.

from fastapi import File, UploadFile

@app.post("/upload/")
def upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}

Объяснение кода

  • UploadFile — это класс, который позволяет получать информацию о файле и его содержимое.
  • File(...) указывает, что параметр будет получен из файла запроса.

Преимущества использования Request Files

  • Удобная работа с файлами: можно легко загружать и обрабатывать файлы в API.
  • Асинхронная обработка: UploadFile поддерживает асинхронные операции, что повышает производительность при работе с большими файлами.

19. Request Forms and Files (Запросы с формами и файлами)

FastAPI позволяет одновременно обрабатывать данные формы и файлы в одном запросе. Это полезно для работы с формами, которые содержат как текстовые поля, так и файлы.

Пример использования

В этом примере мы создаём эндпоинт для загрузки файла с описанием, передаваемым через поле формы.

from fastapi import Form

@app.post("/upload/")
def upload_file(file: UploadFile = File(...), description: str = Form(...)):
    return {"filename": file.filename, "description": description}

Объяснение кода

  • File(...) указывает FastAPI, что параметр file передаётся как файл.
  • Form(...) указывает, что параметр description передаётся как текстовое поле формы.

Преимущества работы с формами и файлами

  • Гибкость: можно принимать текст и файлы в одном запросе.
  • Удобство для пользователей: это облегчает работу с HTML-формами, которые содержат файлы и текстовые поля.