Введение
Всё больше Python-разработчиков переходит на асинхронную архитектуру приложений. Это особенно актуально для веб-фреймворков вроде FastAPI, где высокая производительность достигается за счёт async/await
. Однако большинство традиционных ORM не поддерживают асинхронность. Именно здесь появляется Tortoise-ORM – асинхронная ORM, созданная для нативной поддержки async
операций с базами данных.
Tortoise-ORM вдохновлена Django ORM, проста в освоении, и предлагает мощный инструментарий для построения современных приложений.
Основы работы ORM и особенности Tortoise
Что такое ORM и зачем асинхронность
ORM (Object-Relational Mapping) позволяет разработчику описывать таблицы базы данных как Python-классы. Асинхронность в ORM означает возможность неблокирующей работы с базой данных, что критично для масштабируемых API.
Где использовать Tortoise-ORM
-
В FastAPI или других ASGI-приложениях
-
В микросервисах с высокой нагрузкой
-
В любом проекте, где важна асинхронность и производительность
Установка и настройка
pip install tortoise-orm
Создаём файл models.py
и определяем модель:
from tortoise import fields
from tortoise.models import Model
class Author(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=100)
birth_date = fields.DateField(null=True)
Инициализация в основном скрипте:
from tortoise import Tortoise
await Tortoise.init(
db_url='sqlite://db.sqlite3',
modules={'models': ['models']}
)
await Tortoise.generate_schemas()
Создание моделей в Tortoise-ORM
-
IntField
,CharField
,BooleanField
,DatetimeField
-
ForeignKeyField
— для связей один-ко-многим -
ManyToManyField
,OneToOneField
— поддержка всех типов связей
Пример связи:
class Book(Model):
id = fields.IntField(pk=True)
title = fields.CharField(max_length=200)
author = fields.ForeignKeyField('models.Author', related_name='books')
Асинхронные операции с базой данных
-
Создание записи:
await Author.create(name='Фёдор Достоевский')
-
Чтение:
author = await Author.get(name='Фёдор Достоевский')
-
Обновление:
author.name = 'Ф. М. Достоевский'
await author.save()
-
Удаление:
await author.delete()
-
Фильтрация:
books = await Book.filter(title__contains='Преступление')
Отношения между моделями
Tortoise поддерживает все типы связей, включая ForeignKey
, OneToOne
, ManyToMany
. Связанные объекты можно получить с помощью await
:
book = await Book.get(id=1)
author = await book.author
Миграции и генерация схемы
Tortoise сам по себе не включает систему миграций, но используется сторонний инструмент aerich:
pip install aerich
aerich init -t settings.TORTOISE_ORM
Создание и применение миграций:
aerich init-db
aerich migrate
aerich upgrade
Интеграция с FastAPI
Tortoise легко подключается к FastAPI с помощью middleware и dependency:
from tortoise.contrib.fastapi import register_tortoise
register_tortoise(
app,
db_url='sqlite://db.sqlite3',
modules={'models': ['models']},
generate_schemas=True,
add_exception_handlers=True,
)
Поддерживаемые СУБД
-
SQLite
-
PostgreSQL
-
MySQL
Каждая база имеет свои особенности, но синтаксис Tortoise-ORM остаётся одинаковым.
Тестирование с Tortoise-ORM
Асинхронное тестирование выполняется с использованием pytest-asyncio
. Для изоляции удобно использовать SQLite in-memory:
db_url = 'sqlite://:memory:'
Производительность и оптимизация
-
select_related
— подгрузка ForeignKey -
prefetch_related
— подгрузка ManyToMany и reverse ForeignKey
authors = await Author.all().prefetch_related('books')
-
Поддержка транзакций:
from tortoise.transactions import in_transaction
async with in_transaction():
...
Сравнение с другими ORM
ORM | Асинхронность | Простота | Поддержка миграций | Подходит для |
---|---|---|---|---|
Tortoise-ORM | Да | Высокая | Через aerich | API, FastAPI, ASGI |
SQLAlchemy Async | Да | Средняя | Alembic | Крупные проекты |
Peewee + async | Частично | Высокая | peewee-migrate | Простые проекты |
Поддержка, документация и сообщество
-
Официальный сайт: https://tortoise-orm.readthedocs.io
-
Проект активно развивается
-
Хорошая документация и примеры интеграции
Часто задаваемые вопросы (FAQ)
1. Что такое Tortoise-ORM?
Асинхронная ORM-библиотека для Python, вдохновлённая Django ORM.
2. Поддерживает ли Tortoise-ORM PostgreSQL?
Да, полностью. Также поддерживаются SQLite и MySQL.
3. Как выполнять миграции?
С помощью стороннего инструмента aerich
.
4. Подходит ли Tortoise-ORM для продакшена?
Да, при правильной настройке она надёжна и производительна.
5. Есть ли поддержка Pydantic?
Да, можно использовать Pydantic-схемы для валидации данных в FastAPI.
6. Как работать с транзакциями?
С помощью контекстного менеджера in_transaction()
.
Полный справочник по работе с Tortoise ORM для Python
Установка
pip install tortoise-orm
Для работы с PostgreSQL:
pip install asyncpg
Для SQLite:
pip install aiosqlite
Основные особенности
Возможность | Описание |
---|---|
Поддержка asyncio |
Полностью асинхронный ORM. |
Поддержка SQLite, PostgreSQL, MySQL | Через async-драйверы. |
Стиль, похожий на Django ORM | Классы моделей, filter() , all() , get() . |
Автоматическая генерация схем | Создание таблиц из моделей. |
Простая интеграция с FastAPI, Starlette и др. |
Пример минимального приложения
from tortoise import fields, Tortoise, run_async
from tortoise.models import Model
class User(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=50)
is_active = fields.BooleanField(default=True)
async def run():
await Tortoise.init(
db_url='sqlite://db.sqlite3',
modules={'models': ['__main__']}
)
await Tortoise.generate_schemas()
user = await User.create(name="Alice")
print(await User.all())
run_async(run())
Определение моделей
from tortoise.models import Model
from tortoise import fields
class Author(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=100)
class Book(Model):
id = fields.IntField(pk=True)
title = fields.CharField(max_length=200)
author = fields.ForeignKeyField("models.Author", related_name="books")
published = fields.DateField()
Основные методы ORM
Метод | Описание |
---|---|
Model.create(...) |
Создание объекта. |
Model.get(...) |
Получение одной записи (исключение при отсутствии). |
Model.filter(...) |
Фильтрация. |
Model.all() |
Все записи. |
Model.first() / last() |
Первая / последняя запись. |
Model.update_from_dict() |
Обновление полей. |
Model.delete() |
Удаление записи. |
Model.exists() |
Проверка наличия. |
Примеры запросов
# Создание
user = await User.create(name="Bob")
# Получение
user = await User.get(id=1)
# Фильтрация
users = await User.filter(name__icontains="bo")
# Обновление
user.name = "Bobby"
await user.save()
# Удаление
await user.delete()
Работа со связями
author = await Author.create(name="Толстой")
book = await Book.create(title="Война и мир", author=author)
# Получение книг автора
books = await author.books.all()
Prefetch и select_related
Метод | Описание |
---|---|
select_related() |
Жадная загрузка внешнего ключа (FK). |
prefetch_related() |
Жадная загрузка M2M или reverse FK. |
# Получить книги с авторами (join)
books = await Book.all().select_related('author')
# Получить авторов с их книгами (отдельным запросом)
authors = await Author.all().prefetch_related('books')
Работа с Pydantic (FastAPI)
pip install tortoise-orm[asyncpg] pydantic
from tortoise.contrib.pydantic import pydantic_model_creator
User_Pydantic = pydantic_model_creator(User)
Миграции (Tortoise не использует Alembic)
Для автоматической генерации таблиц:
await Tortoise.generate_schemas()
Для более продвинутого управления — использовать внешние инструменты, например Aerich
:
pip install aerich
Инициализация (в FastAPI или вручную)
from tortoise.contrib.fastapi import register_tortoise
register_tortoise(
app,
db_url="sqlite://db.sqlite3",
modules={"models": ["app.models"]},
generate_schemas=True,
add_exception_handlers=True,
)
Поддержка типов полей
Поле | Описание |
---|---|
IntField |
Целое число. |
CharField(max_length) |
Строка. |
BooleanField() |
Логическое значение. |
DateField() / DatetimeField() |
Дата и время. |
JSONField() |
Хранение JSON. |
ForeignKeyField() |
Связь многие-к-одному. |
ManyToManyField() |
Связь многие-ко-многим. |
Когда использовать Tortoise ORM
-
Когда ты пишешь асинхронное приложение (FastAPI, Starlette, Quart).
-
Когда хочешь Django-подобный стиль без всего Django.
-
Для простых или средних по размеру проектов с акцентом на скорость.
-