📘 Overview
- What is it?: SQLAlchemy is the Python SQL toolkit and Object Relational Mapper (ORM) that gives application developers the full power and flexibility of SQL. It provides a full suite of well-known enterprise-level persistence patterns, designed for efficient and high-performance database access.
- Key Features:
- ORM (Object-Relational Mapping): Map database tables to Python classes and operations, automatically syncing object state changes to the database.
- SQL Expression Language (Core): A Pythonic syntax for building SQL queries, independent of the ORM layer.
- Connection Pooling: Automatic, high-performance connection pooling and transaction management.
- Installation:
pip install sqlalchemy
🧾 Core Concepts
- Engine: The entry point for database communication. It manages the connection pool and dialect behavior (e.g. SQLite, PostgreSQL).
- Declarative Base: The base class for defining database tables as Python objects. Inherited classes map attributes to table columns.
- Session: The transaction manager. It keeps track of modifications (inserts, updates, deletes) and executes them on commit/flush.
- Relationship: Links records in different tables (e.g., One-to-Many, Many-to-Many) using foreign keys, simplifying object-graph traversal.
💻 Common Code Patterns & Cheat Sheet
- Defining Models & Creating Database:
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey from sqlalchemy.orm import declarative_base, relationship # 1. Setup Engine & Base engine = create_engine("sqlite:///example.db", echo=True) Base = declarative_base() # 2. Define Models class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) name = Column(String(50)) emails = relationship("Email", back_populates="user") class Email(Base): __tablename__ = "emails" id = Column(Integer, primary_key=True) email_address = Column(String(100), nullable=False) user_id = Column(Integer, ForeignKey("users.id")) user = relationship("User", back_populates="emails") # 3. Create Tables Base.metadata.create_all(engine) - CRUD Operations:
from sqlalchemy.orm import sessionmaker # Create Session Class Session = sessionmaker(bind=engine) session = Session() # Create (Insert) new_user = User(name="Alice") new_email = Email(email_address="alice@example.com", user=new_user) session.add(new_user) session.add(new_email) session.commit() # Read (Select) user = session.query(User).filter_by(name="Alice").first() print(user.emails[0].email_address) # Update user.name = "Alice Smith" session.commit() # Delete session.delete(user) session.commit()
💡 Best Practices & Tips
- N+1 Query Prevention: By default, SQLAlchemy relationships use lazy loading. Use
joinedload(e.g.from sqlalchemy.orm import joinedload; session.query(User).options(joinedload(User.emails))) to perform an SQL JOIN and fetch related items in a single query, preventing performance bottlenecks. - Context Managers for Sessions: Wrap database sessions in context managers (like
with sessionmaker()() as session:) to automatically close connections and rollback transactions on error. - Alembic Migrations: For production databases, always use Alembic (the companion migration tool) to version and apply database schema changes rather than running
Base.metadata.create_all().