Когда речь заходит об использовании ORM в Python, многие сразу вспоминают SQLAlchemy. Это мощный инструмент для работы с базами данных, но для новичков его порог входа может быть довольно высоким. Особенно когда дело доходит до асинхронных приложений или сложных моделей данных. Если вы ищете более простой, интуитивно понятный и лёгкий в освоении инструмент, обратите внимание на Tortoise ORM.
Работа с Tortoise будет особенно простой для тех, кто уже знаком с Django ORM, так как многие концепции и синтаксис этих библиотек очень похожи. При этом Tortoise ORM поддерживает асинхронные запросы к базе данных, что делает её отличным выбором для современных асинхронных приложений.
Установка
Tortoise ORM поддерживает различные базы данных, такие как PostgreSQL и MySQL. Для работы с PostgreSQL используйте версию tortoise-orm[asyncpg]
, а для MySQL — tortoise-orm[asyncmy]
.
# Для PostgreSQL
pip install tortoise-orm[asyncpg]
# Для MySQL
pip install tortoise-orm[asyncmy]
Сравнение Tortoise ORM и SQLAlchemy
Для начала посмотрим, как отличаются подходы к созданию моделей и их использованию в Tortoise ORM и SQLAlchemy.
Модель в SQLAlchemy
Пример модели User
, написанной с использованием SQLAlchemy:
import datetime
from sqlalchemy import BigInteger, String, Integer, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
__abstract__ = True
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
class User(Base):
__tablename__ = "user"
telegram_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
first_name: Mapped[str] = mapped_column(String, nullable=False)
last_name: Mapped[str] = mapped_column(String, nullable=True)
username: Mapped[str] = mapped_column(String, nullable=True)
language_code: Mapped[str] = mapped_column(String, nullable=False)
created_at: Mapped[datetime.datetime] = mapped_column(server_default=func.now(), default=datetime.datetime.now)
Модель в Tortoise ORM
Теперь посмотрим, как будет выглядеть аналогичная модель в Tortoise ORM:
from tortoise.models import Model
from tortoise import fields
import datetime
class User(Model):
id = fields.IntField(pk=True)
telegram_id = fields.BigIntField(null=False)
first_name = fields.CharField(max_length=255)
last_name = fields.CharField(max_length=255, null=True)
username = fields.CharField(max_length=255, null=True)
language_code = fields.CharField(max_length=10, null=False)
created_at = fields.DatetimeField(auto_now_add=True)
class Meta:
table = "user"
Обратите внимание, насколько синтаксис в Tortoise ORM проще. Модель создаётся как класс, наследуемый от Model
, а поля данных задаются через типы из tortoise.fields
. В "Мета-классе" указываем, как будет называться таблица модели. На этом этапе главное не начать думать, что работаешь в Django 😉.
Пример получения или создания записи
Теперь давайте сравним, как в SQLAlchemy и Tortoise ORM можно получить или создать запись пользователя.
Пример в SQLAlchemy
SQLAlchemy требует явного использования сессий, запросов и обработчиков. Вот пример функции для получения или создания пользователя:
async def get_or_create_user(user: UserSchemaBaseInput) -> UserSchemaOutput:
async with session_maker() as session:
query = select(User).where(user.telegram_id User.telegram_id)
result = await session.execute(query)
exist_user = result.scalar_one_or_none()
if exist_user:
return UserSchemaOutput.model_validate(obj=exist_user, from_attributes=True)
user_query = (
insert(User)
.values(**user.dict())
.returning(
User.id,
User.telegram_id,
User.first_name,
User.last_name,
User.username,
User.created_at,
User.language_code,
)
)
result = await session.execute(user_query)
await session.commit()
new_user = result.mappings().first()
return UserSchemaOutput.model_validate(obj=new_user, from_attributes=True)
Как видим, получается достаточно много действий.
Пример в Tortoise ORM
Теперь аналогичный пример в Tortoise ORM:
async def get_or_create_user(telegram_id: int, first_name: str, last_name: str, username: str, language_code: str):
user, created = await User.get_or_create(
telegram_id=telegram_id,
defaults={
"first_name": first_name,
"last_name": last_name,
"username": username,
"language_code": language_code,
"created_at": datetime.datetime.now(),
}
)
return user, created
В Tortoise ORM этот процесс значительно проще: мы используем метод get_or_create
, который выполняет поиск записи по указанным полям и создаёт новую, если такая запись не найдена. Здесь нет необходимости явно работать с сессиями или писать SQL-запросы — всё выполняется через ORM.
Использование Pydantic с Tortoise ORM
SQLAlchemy и Pydantic часто используются вместе для валидации и сериализации данных, но в Tortoise ORM нет строгой необходимости использовать Pydantic. Tortoise имеет встроенные методы для сериализации моделей, например, метод .to_dict()
.
Тем не менее, если вы уже используете Pydantic в вашем проекте, его можно легко интегрировать с Tortoise ORM. Важно отметить, что Tortoise ORM также имеет встроенную поддержку Pydantic через методы .model_validate()
для создания и валидации схем данных.
Пример использования Pydantic с Tortoise ORM:
from pydantic import BaseModel
class UserSchema(BaseModel):
telegram_id: int
first_name: str
last_name: str | None
username: str | None
language_code: str
async def get_user_schema(user_id: int) -> UserSchema:
user = await User.get(id=user_id)
return UserSchema.model_validate(user, from_attributes=True)
Таким образом, Tortoise ORM прекрасно сочетается с Pydantic, но также может обходиться и без него.
Заключение
Tortoise ORM — это отличная альтернатива для тех, кто ищет простой и понятный способ работы с базами данных в небольших асинхронных приложениях. Если SQLAlchemy кажется сложным, Tortoise предложит более интуитивный подход, сохраняя при этом поддержку всех современных возможностей ORM, таких как асинхронность и валидация данных.
Напишите в комментариях, стоит ли его применить в одном из будущих гайдов, для более конкретного примера использования?
Добавить комментарий:
Войдите чтобы добавить комментарий.
Комментарии пользователей:
Нет комментариев
Реклама
Соседние посты
Tortoise ORM - Простая асинхронная альтернатива SQLAlchemyПагинация в aiogram 3
Обсуждение
Обсудить или задать вопрос можно в комментариях к посту в Telegram
Теги
PostgreSQL SQLite ORM MySQL работа с БД SQLAlchemy Pydantic Tortoise ОРМ Модели БД База ДанныхСсылки
Реклама