Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Сессия в Django ORM
Краткий ответ
Сессия в Django ORM — это объект, который управляет жизненным циклом объектов модели и их взаимодействием с базой данных. В Django сессия работает автоматически и неявно.
Важное уточнение: Django vs SQLAlchemy
Django ORM (встроенная ORM)
В Django сессия работает неявно и автоматически:
from django.db import models
class User(models.Model):
name = models.CharField(max_length=255)
email = models.EmailField(unique=True)
# Создание
user = User.objects.create(name="John", email="john@example.com")
# Чтение
user = User.objects.get(id=1)
# Обновление и сохранение
user.name = "Jane"
user.save()
# Удаление
user.delete()
SQLAlchemy (отдельная ORM)
В SQLAlchemy сессия работает явно:
from sqlalchemy.orm import Session
with Session(engine) as session:
user = User(name="John", email="john@example.com")
session.add(user)
session.commit()
user = session.query(User).filter_by(id=1).first()
user.name = "Jane"
session.commit()
Что такое сессия в контексте ORM?
Сессия — это:
- Контекст работы с объектами БД
- Кэш объектов, загруженных из БД
- Транзакция — группа операций, которые либо все выполнятся, либо все откатятся
- Отслеживание изменений — сессия видит, какие объекты изменились
В Django: Явное управление транзакциями
from django.db import transaction
# Способ 1: Декоратор
@transaction.atomic
def create_user_with_profile():
user = User.objects.create(name="John")
profile = Profile.objects.create(user=user, bio="Hi")
# Способ 2: Context manager
with transaction.atomic():
user = User.objects.create(name="John")
profile = Profile.objects.create(user=user, bio="Hi")
# Способ 3: Savepoint
with transaction.atomic():
try:
user = User.objects.create(name="John")
with transaction.atomic():
profile = Profile.objects.create(user=user)
except Exception:
pass
В SQLAlchemy: Явная сессия
from sqlalchemy.orm import Session
# Способ 1: Контекстный менеджер
with Session(engine) as session:
user = User(name="John")
session.add(user)
session.commit()
# Способ 2: Явное управление
session = Session(engine)
try:
user = User(name="John")
session.add(user)
session.commit()
except Exception:
session.rollback()
raise
finally:
session.close()
# Способ 3: Вложенные транзакции
with Session(engine) as session:
user = User(name="John")
session.add(user)
session.flush()
try:
with session.begin_nested():
profile = Profile(user_id=user.id)
session.add(profile)
except Exception:
pass
session.commit()
Состояния объекта в сессии
SQLAlchemy (явное)
session = Session(engine)
# 1. Transient — объект создан, но не в сессии
user = User(name="John")
print(user in session)
# 2. Pending — добавлен в сессию, но не в БД
session.add(user)
print(user in session)
# 3. Persistent — в сессии и в БД
session.commit()
print(user.id)
# 4. Detached — был в сессии, но сессия закрыта
session.close()
print(user in session)
Django (неявное)
В Django состояния менее явные:
# Transient
user = User(name="John")
print(user.id)
# Persistent
user.save()
print(user.id)
# После save() всё работает
user.name = "Jane"
user.save()
Проблемы с сессиями
1. Lazy Loading (N+1 проблема)
# Django
users = User.objects.all()
for user in users:
print(user.profile.bio)
# Решение: select_related
users = User.objects.select_related("profile").all()
# SQLAlchemy
with Session(engine) as session:
users = session.query(User).all()
for user in users:
print(user.profile.bio)
# Решение: joinedload
users = session.query(User).options(joinedload(User.profile))
2. Detached объект (SQLAlchemy проблема)
with Session(engine) as session:
user = session.query(User).get(1)
print(user.profile.bio) # DetachedInstanceError!
3. Identity Map (кэш)
# SQLAlchemy
with Session(engine) as session:
user1 = session.query(User).get(1)
user2 = session.query(User).get(1)
print(user1 is user2) # True!
# Django
user1 = User.objects.get(id=1)
user2 = User.objects.get(id=1)
print(user1 is user2) # False
FastAPI + SQLAlchemy (практический пример)
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
engine = create_engine("postgresql://...")
SessionLocal = sessionmaker(bind=engine)
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/users/")
async def create_user(
user_data: dict,
db: Session = Depends(get_db)
):
user = User(**user_data)
db.add(user)
db.commit()
db.refresh(user)
return user
@app.get("/users/{user_id}")
async def get_user(
user_id: int,
db: Session = Depends(get_db)
):
user = db.query(User).get(user_id)
if not user:
raise HTTPException(status_code=404)
return user
Лучшие практики
Django
# Хорошо: select_related для избежания N+1
users = User.objects.select_related("profile").all()
# Хорошо: transaction.atomic
@transaction.atomic
def create_user_with_profile():
user = User.objects.create(name="John")
Profile.objects.create(user=user)
SQLAlchemy
# Хорошо: контекстный менеджер
with Session(engine) as session:
user = User(name="John")
session.add(user)
session.commit()
# Хорошо: joinedload для N+1
users = session.query(User).options(joinedload(User.profile)).all()
Вывод
Сессия — это контекст работы с БД. В Django она неявная и автоматическая, в SQLAlchemy — явная. Главное — понимать жизненный цикл объектов и оптимизировать N+1 проблемы.