← Назад к вопросам

C какими ORM работал

1.0 Junior🔥 191 комментариев
#Django#Базы данных (SQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

С какими ORM работал?

В своей карьере работал с несколькими популярными ORM для Python, каждая из которых имеет свои сильные стороны и применение.

1. SQLAlchemy (2.0+) — мой основной выбор

Самая мощная и гибкая ORM в Python. Работал как с Core, так и с ORM слоем.

Основное применение:

from sqlalchemy import create_engine, Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import declarative_base, Session, relationship
from datetime import datetime

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True)
    username = Column(String(50), unique=True, nullable=False)
    email = Column(String(120), unique=True, nullable=False)
    created_at = Column(DateTime, default=lambda: datetime.now(UTC))
    
    posts = relationship('Post', back_populates='author', cascade='all, delete-orphan')

class Post(Base):
    __tablename__ = 'posts'
    
    id = Column(Integer, primary_key=True)
    title = Column(String(255), nullable=False)
    content = Column(String, nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
    created_at = Column(DateTime, default=lambda: datetime.now(UTC))
    
    author = relationship('User', back_populates='posts')

engine = create_engine('postgresql://user:pass@localhost/dbname')
Base.metadata.create_all(engine)

# Использование
with Session(engine) as session:
    # Create
    user = User(username='alice', email='alice@example.com')
    session.add(user)
    session.commit()
    
    # Read
    user = session.query(User).filter(User.username == 'alice').first()
    
    # Update
    user.email = 'alice_new@example.com'
    session.commit()
    
    # Delete
    session.delete(user)
    session.commit()

Преимущества:

  • Гибкость: можно писать как высокоуровневый ORM код, так и raw SQL
  • Мощные relationships и lazy loading strategies
  • Встроенная поддержка transactions и session management
  • Отличная документация
  • Поддержка множества БД (PostgreSQL, MySQL, SQLite, Oracle и т.д.)

Недостатки:

  • Крутая кривая обучения
  • Иногда медленнее простых решений
  • Может быть overkill для простых приложений

2. Django ORM — для полного фреймворка

Использовал для проектов на Django, где ORM интегрирована в фреймворк.

from django.db import models
from django.utils import timezone

class User(models.Model):
    username = models.CharField(max_length=50, unique=True)
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        ordering = ['-created_at']
    
    def __str__(self):
        return self.username

class Post(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        ordering = ['-created_at']

# Использование (в views)
from django.shortcuts import get_object_or_404

def user_posts(request, user_id):
    user = get_object_or_404(User, id=user_id)
    posts = user.posts.all()  # QuerySet (ленивый)
    
    # Фильтрация
    posts = posts.filter(created_at__year=2024)
    
    # Агрегация
    post_count = posts.count()
    
    # Аннотация
    from django.db.models import Count
    users_with_counts = User.objects.annotate(post_count=Count('posts'))
    
    return render(request, 'posts.html', {'posts': posts})

Преимущества:

  • Простая и интуитивная
  • Отличная интеграция с Django админкой
  • Встроенная миграции (Django Migrations)
  • Быстро писать для стандартных задач

Недостатки:

  • Тесно связана с Django (сложно использовать отдельно)
  • Менее гибкая, чем SQLAlchemy
  • Сложнее писать сложные queries

3. Peewee — лёгкая ORM

Использовал для небольших проектов, где нужна простая ORM без Django.

from peewee import SqliteDatabase, Model, CharField, ForeignKeyField, DateTimeField
from datetime import datetime

db = SqliteDatabase('my_app.db')

class BaseModel(Model):
    class Meta:
        database = db

class User(BaseModel):
    username = CharField(unique=True)
    email = CharField(unique=True)
    created_at = DateTimeField(default=datetime.now)

class Post(BaseModel):
    title = CharField()
    content = CharField()
    author = ForeignKeyField(User, backref='posts')
    created_at = DateTimeField(default=datetime.now)

db.create_tables([User, Post])

# Использование
user = User.create(username='bob', email='bob@example.com')
post = Post.create(title='Hello', content='World', author=user)

# Query
user_posts = Post.select().where(Post.author == user)
for post in user_posts:
    print(post.title)

Преимущества:

  • Очень простая и лёгкая
  • Низкий overhead
  • Идеально для небольших проектов
  • Хорошо работает с SQLite

Недостатки:

  • Менее мощная, чем SQLAlchemy
  • Меньшее сообщество
  • Сложнее для сложных relationships

4. Tortoise ORM — для async приложений

Использовал для асинхронных проектов на FastAPI/aiohttp.

from tortoise import fields, run_async
from tortoise.models import Model
from tortoise.queryset import QuerySet

class User(Model):
    id = fields.IntField(pk=True)
    username = fields.CharField(max_length=50, unique=True)
    email = fields.CharField(max_length=120, unique=True)
    created_at = fields.DatetimeField(auto_now_add=True)
    
    posts: QuerySet  # type hint
    
    class Meta:
        table = "users"

class Post(Model):
    id = fields.IntField(pk=True)
    title = fields.CharField(max_length=255)
    content = fields.TextField()
    author: fields.ForeignKeyRelation[User] = fields.ForeignKeyField(
        'models.User', related_name='posts', on_delete=fields.CASCADE
    )
    created_at = fields.DatetimeField(auto_now_add=True)
    
    class Meta:
        table = "posts"

# Async использование
async def get_user_posts(user_id: int):
    user = await User.get(id=user_id)
    posts = await user.posts.all()
    return posts

async def main():
    await Tortoise.init(
        db_url='sqlite://:memory:',
        modules={'models': ['__main__']}
    )
    await Tortoise.generate_schemas()
    
    # CRUD
    user = await User.create(username='alice', email='alice@example.com')
    await Post.create(title='Hello', content='World', author=user)
    
    posts = await get_user_posts(user.id)
    for post in posts:
        print(post.title)

if __name__ == '__main__':
    run_async(main())

Преимущества:

  • Native async/await поддержка
  • Отличная для FastAPI
  • Асинхронные миграции

Недостатки:

  • Молодой проект
  • Меньше сообщества
  • Может быть менее стабильным

5. SQLModel — новый подход

Экспериментировал с SQLModel (комбо Pydantic + SQLAlchemy) для FastAPI.

from sqlmodel import SQLModel, Field, create_engine, Session, select
from typing import Optional, List

class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    username: str = Field(unique=True, index=True)
    email: str = Field(unique=True, index=True)
    posts: List['Post'] = []

class Post(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str
    content: str
    user_id: int = Field(foreign_key='user.id')
    author: Optional[User] = None

engine = create_engine('sqlite:///database.db')
SQLModel.metadata.create_all(engine)

# Использование
def create_user(user: User):
    with Session(engine) as session:
        session.add(user)
        session.commit()
        session.refresh(user)
        return user

def get_users():
    with Session(engine) as session:
        statement = select(User)
        return session.exec(statement).all()

Преимущества:

  • Единая модель для БД и API
  • Отличная типизация
  • Автоматическая валидация Pydantic
  • Идеально для FastAPI

Недостатки:

  • Ещё молодой проект
  • Меньше функциональности, чем SQLAlchemy

Мой обычный выбор:

ПроектORMПричина
FastAPI (sync)SQLAlchemy 2.0Мощь и гибкость
FastAPI (async)Tortoise ORMNative async
DjangoDjango ORMВстроенная в фреймворк
Pequые скриптыPeeweeПростота
МикросервисыSQLAlchemy CoreСкорость и контроль

Практические советы при выборе ORM:

  1. Размер проекта: маленький → Peewee, большой → SQLAlchemy
  2. Async требуется? → Tortoise, SQLAlchemy с asyncio
  3. Используешь Django? → Django ORM
  4. FastAPI + хотишь лучше? → SQLAlchemy 2.0 или SQLModel
  5. Производительность критична? → SQLAlchemy Core или raw SQL

Типичные ошибки при работе с ORM:

# ❌ N+1 проблема
users = User.objects.all()  # 1 query
for user in users:
    print(user.posts.count())  # N additional queries

# ✅ Использовать select_related/prefetch_related (Django)
users = User.objects.prefetch_related('posts').all()

# ✅ Использовать joinedload (SQLAlchemy)
from sqlalchemy.orm import joinedload
users = session.query(User).options(joinedload(User.posts)).all()
C какими ORM работал | PrepBro