Какие знаешь два основных компонента в SQLAlchemy?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Два основных компонента в SQLAlchemy
SQLAlchemy — это мощный ORM (Object-Relational Mapping) фреймворк для Python. Она состоит из двух основных компонентов, которые работают на разных уровнях абстракции.
1. Core (Ядро) — SQL Expression Language
SQL Expression Language — это низкоуровневый компонент, который работает непосредственно с SQL.
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select
# Создание таблицы через Core
metadata = MetaData()
users_table = Table(
'users',
metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('email', String(100), unique=True)
)
# Создание двигателя и подключения
engine = create_engine('postgresql://user:password@localhost/dbname')
# SQL SELECT через Core
stmt = select(users_table).where(users_table.c.id == 1)
with engine.connect() as conn:
result = conn.execute(stmt)
for row in result:
print(row)
Преимущества Core:
- Полный контроль над SQL
- Не требует определения классов
- Работает с любым подходом
- Строит SQL программно
Использование Core для различных операций:
from sqlalchemy import select, insert, update, delete
# INSERT
stmt = insert(users_table).values(name='John', email='john@example.com')
result = conn.execute(stmt)
# UPDATE
stmt = update(users_table).where(users_table.c.id == 1).values(name='Jane')
result = conn.execute(stmt)
# DELETE
stmt = delete(users_table).where(users_table.c.id == 1)
result = conn.execute(stmt)
# SELECT с условиями и JOIN
from sqlalchemy import and_, or_
stmt = select(users_table).where(
and_(
users_table.c.name.like('J%'),
users_table.c.email != None
)
)
# JOIN
posts_table = Table('posts', metadata, Column('id', Integer, primary_key=True), ...)
stmt = select(users_table, posts_table).join(
posts_table,
users_table.c.id == posts_table.c.user_id
)
2. ORM (Object-Relational Mapping) — Declarative
ORM компонент позволяет работать с таблицами как с Python классами.
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import declarative_base, relationship, Session
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id: int = Column(Integer, primary_key=True)
name: str = Column(String(50), nullable=False)
email: str = Column(String(100), unique=True, nullable=False)
posts = relationship('Post', back_populates='author')
def __repr__(self):
return f'<User(id={self.id}, name={self.name}, email={self.email})>'
class Post(Base):
__tablename__ = 'posts'
id: int = Column(Integer, primary_key=True)
title: str = Column(String(200), nullable=False)
content: str = Column(String, nullable=False)
user_id: int = Column(Integer, ForeignKey('users.id'), nullable=False)
author = relationship('User', back_populates='posts')
def __repr__(self):
return f'<Post(id={self.id}, title={self.title})>'
# Создание таблиц
engine = create_engine('postgresql://user:password@localhost/dbname')
Base.metadata.create_all(engine)
# Работа с ORM
with Session(engine) as session:
# CREATE
user = User(name='John', email='john@example.com')
session.add(user)
session.commit()
# READ
john = session.query(User).filter_by(name='John').first()
print(john) # <User(id=1, name=John, email=john@example.com)>
# UPDATE
john.email = 'newemail@example.com'
session.commit()
# DELETE
session.delete(john)
session.commit()
# Relationships
user = session.query(User).filter_by(id=1).first()
for post in user.posts: # Автоматическая загрузка связанных постов
print(post.title)
Сравнение Core и ORM
| Аспект | Core | ORM |
|---|---|---|
| Абстракция | Низкая | Высокая |
| Контроль над SQL | Полный | Меньше |
| Скорость разработки | Медленнее | Быстрее |
| Производительность | Быстрее | Немного медленнее |
| Сложность | Проще | Сложнее |
| Идеально для | Сложные запросы | Стандартные операции |
Когда использовать Core
# Сложные запросы с множественными JOIN и условиями
from sqlalchemy import and_, or_, func
query = select(
users_table.c.id,
users_table.c.name,
func.count(posts_table.c.id).label('post_count')
).join(
posts_table,
users_table.c.id == posts_table.c.user_id
).where(
and_(
users_table.c.created_at > '2024-01-01',
or_(
posts_table.c.views > 100,
posts_table.c.likes > 50
)
)
).group_by(users_table.c.id)
# Этот запрос проще писать в Core чем в ORM
with engine.connect() as conn:
result = conn.execute(query)
Когда использовать ORM
# Простые CRUD операции
with Session(engine) as session:
# Создание
user = User(name='Alice', email='alice@example.com')
session.add(user)
session.commit()
# Чтение
users = session.query(User).all()
# Обновление
user.name = 'Alicia'
session.commit()
# Удаление
session.delete(user)
session.commit()
# ORM с relationships — очень удобно
user = session.query(User).filter_by(id=1).first()
for post in user.posts: # Автоматически загружает related objects
print(post.title)
Гибридный подход
Вы можете использовать оба компонента вместе:
from sqlalchemy import text
# Используем ORM для простых операций
user = session.query(User).filter_by(id=1).first()
# Используем raw SQL для сложного запроса
result = session.execute(
text('SELECT * FROM users WHERE created_at > :date'),
{'date': '2024-01-01'}
)
# Используем Core для сложного запроса
from sqlalchemy import select, func, desc
query = select(
User.id,
User.name,
func.count(Post.id).label('post_count')
).join(Post).group_by(User.id).order_by(desc('post_count'))
results = session.execute(query).fetchall()
SQLAlchemy 2.0 - новый стиль
from sqlalchemy import create_engine, select
from sqlalchemy.orm import declarative_base, Session
engine = create_engine('postgresql://...')
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id: int = Column(Integer, primary_key=True)
name: str = Column(String)
# SQLAlchemy 2.0 рекомендует этот стиль
with Session(engine) as session:
# Используй select() вместо query()
stmt = select(User).where(User.id == 1)
user = session.scalars(stmt).first()
print(user)
Выводы
Два основных компонента SQLAlchemy:
-
Core (SQL Expression Language) — низкоуровневый, полный контроль над SQL
- Используй для сложных запросов
- Лучше для performance-critical кода
- Работает без определения классов
-
ORM (Object-Relational Mapping) — высокоуровневый, работаешь с классами Python
- Используй для стандартных CRUD операций
- Лучше для быстрой разработки
- Отлично работает с relationships
Best Practice:
- Начни с ORM для простоты
- Переходи на Core когда нужны сложные запросы
- Комбинируй оба подхода в большом проекте
- В SQLAlchemy 2.0 используй select() вместо query()
Знание обоих компонентов делает тебя гибким разработчиком, способным решать задачи на оптимальном уровне абстракции.