Let's Drink Heavily with SQL

Noah Seger
Lead Developer, Texas Tribune


In [ ]:
pip install sqlalchemy

SQLAlchemy

  • Enterprise-level toolkit (not an ORM)
  • Only ORM that lets your take full advantage of your database
  • Models the whole SQL domain
    • engine: backend that can generate connections with a set of capabilities
    • table,s columns, indexes
    • data types
    • functions, operators, views
    • metadata: object that holds complete set of tables, constraints, and relationships, bound to an engine

In [ ]:
from django.db.models.loading import cache
cache.get_apps()
# one global app-cache

Several layers of APIs

  • SQL expression language
  • object-relational mapper
  • declarative base

In [ ]:
from sqlalchemy import *

engine = create_engine('sqlite:///tx_people.db', echo=True)
metadata = MetaData(bind=engine)
connection = metadata.bind

politicians = Table(
    'politicians',
    metadata,
    Column('id', Integer, primary_key=True),
    Column('politician_name', String, nullable=False)
)

metadata.create_all()

connection.execute(politicians.insert(), [
    {'politician_name': 'Rick Perry'},
    {'politician_name': 'Wendy Davis'},
])

It's a toolkit; there are high-level tools, as well.


In [ ]:
from sqlalchemy import *

Base = declarative_base()

class Politician(Base):
    __tablename__ = 'politicians'
    id = Column(Integer, primary_key=True)
    name = Column(string, nullable=False)
    
class Office(Base):
    __tablename__ = 'office'
    # ...

engine = ''...
Base.metadata.creat_all(engine)

Unit of Work and the Session


In [ ]:
politician = Politician('Rick Perry')

governor = Office(politician, title='Governor')

#... more transactions

# commit session all at once

SQLAlchemy vs. Django ORM


In [ ]:
# SQLAlchemy
session.query(Politician).all()

# Django
Politician.objects.all()

In [ ]:
# SQLAlchemy (can handle multi-column PKs)
session.query(Politician).get(1)

# Django
Politician.objects.get(pk=1)

In [ ]:
# SQLAlchemy
session.query(Politician).first()

# Django
next(iter(Politician.objects.all(), None))

More good stuff

  • great postgresql integration
    • arrays, ranges, Hstore, and a lot more
  • operators
    • filter by keys in a schema-less postgres store
    • politicians.c.data.op('->>')('city') == 'Austin'
  • functions

    • print(func.current_timestampe()) # CURRENT_TIMESTAMP
  • Reflection and compilation

    • grab existing tables without modelling them
    • can compile generated SQL into tuples for use in, say, non-blocking asynchronous database calls

"Nobody ever got in trouble for using SQLAlchemy."

Could use SQLAlchmey to reflect Django models and make complex queries

With flask + sqlalchemy, there is a decent migration tool

Author of SQLAlchemy is working on a migration tool