SlideShare a Scribd company logo
1 of 87
Download to read offline
Install
● Python 2.5 or 2.6 (or pysqlite for 2.4)
● SQLAlchemy 0.5

       1. easy_install, if needed
          ● wget http://peak.telecommunity.com/dist/ez_setup.py

          ● python ez_setup.py

    2. easy_install sqlalchemy==0.5.8

●   http://old.utahpython.org/sqla2010/
Michael Bayer
Michael Bayer is a software architect in New
 York City and is the creator of SQLAlchemy.

http://techspot.zzzeek.org/
@zzzeek
ORM 101 – the bad old days

c = db.cursor()
sql = "SELECT * FROM users WHERE name = %s"
c.execute(sql, (name,))
user = User(*c.fetchone())

user.last_login_at = time.time()
sql = "UPDATE users SET last_login_at = %s WHERE name = %s"
c.execute(sql, (user.last_login_at, name0))
c.commit()
ORM 101 – and there was light

session = Session()
user = session.query(User).filter(name=name).one()

user.last_login_at = time.time()

session.commit()
The devil is in the details
● Compound WHERE clauses, subqueries,
  outer joins, sql functions, ...
● Eager/lazy loading

● Support for legacy schemas

● Inheritance

● Conceptual integrity

● Setup overhead

● Database support
What SQLAlchemy is not
[Demolition photo]
Tough love?

“Disproving the myth of 'the best database layer is
the one that makes the database invisible' is a
primary philosophy of SA. If you don't want to deal
with SQL, then there's little point to using a
[relational] database in the first place.”
Technical excellence
●   PK: multi-column is fine; mutable is fine; any
    data type is fine; doesn't have to be named
    “id”
    http://blogs.ittoolbox.com/database/soup/archives/primary-keyvil-part-i-73
● Recognizes all database defaults instead of
  allowing a few special cases like “created_at”
● Doesn't make up its own query language

● No XML

● Introspection or define-tables-in-Python

● Session/unit-of-work based

● Migrations
Supported databases
PostgreSQL
MySQL
SQLite
Firebird
Oracle
MSSQL
Sybase
DB2
Informix
SAPDB
MSAccess
Database dependence: a feature
●   Performance
     –   Functions, partial indexes, bitmap indexes,
         partitioning, replication, ...
●   Features
     –   Views, arrays, recursive joins, full-text searching,
         ...

See also:
 http://powerpostgresql.com/Downloads/database_d
Caching
Beaker integration is an example w/ the 0.6
distribution (currently in beta)
Questions
Today's agenda: fundamentals
Data Mapper vs Active Record
SA Fundamentals
Mapping basics
Queries
Sessions & the identity map
Relationship lifecycle
Backrefs
Agenda 2: More ORM details
Multi-object queries
One-to-one
Many-to-many
Relation queries
Eager/lazy loading
Transactions
Extensions and related projects
Agenda 3: Extensions and
        related projects
Migrate
FormAlchemy
SqlSoup
Elixir
z3c.sqlalchemy
Two ORM patterns
Active Record
Data Mapper
Active Record
Data Mapper
SQLAlchemy supports both
●   Declarative plugin for common simple
    situations
●   Full data mapper power when you need it
Tables for this tutorial

users
addresses
orders
orderitems
keywords
itemkeywords
Tables

users = Table('users', metadata,
    Column('user_id', Integer, primary_key = True),
    Column('name', String(40)))

users = Table('users', metadata, autoload=True)

users = Table('users', metadata, autoload=True,
    Column('name', String(40), default='Jonathan'))
Legacy columns

ack = Table('ACK110030', metadata,
            Column('ITMNUMBER', Integer,
                   primary_key=True, key='id'),
            Column('MNFCENTERLC_I', Integer,
                   ForeignKey('MFC43222.id'),
                   key='manufacturing_center_id'),
            ...)
Setup from scratch

engine = create_engine('sqlite:///:memory:', echo=True)
metadata = MetaData()
metadata.bind = engine
Session = sessionmaker(bind=engine)

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
Quick setup

http://old.utahpython.org/sqla2010/

from tutorial_tables import *
create()
data()
Table + mapped class together

class Order(Base):
    __tablename__ = 'orders'
    order_id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey(users.c.user_id))
    description = Column('description', String(50))
    isopen = Column(Integer, ColumnDefault(1))
Full data mapper pattern

orders = Table('orders', metadata,
    Column('order_id', Integer, ...),
    Column('user_id', Integer, ForeignKey(users.c.user_id)),
    Column('description', String(50)),
    Column('isopen', Integer, ColumnDefault(1)),

class Order(object): pass

mapper(Order, orders)
The way we will do mapping

class Order(Base):
    __table__ = orders
Querying

session = Session()
q = session.query(Order)
print q

.all
.get
.first, .one
Query modification

q = session.query(Order)

.filter
.filter_by
.order_by [desc, asc]
.limit, .offset
Operators

== >= <= > <

~ | &
not_ or_ and_

in_

between like startswith endswith
Some examples

q = session.query(Order)

q.filter_by(user_id=7).order_by(Order.isopen).first()

q.filter(Order.description.like('order%')).all()

q.filter((Order.user_id==7) | (Order.isopen==1)).all()
q.filter(or_(Order.user_id==7, Order.isopen==1)).all()
Slicing: limit/offset sugar

q = session.query(Order)
q.limit(1).offset(2)

q[2:3]
Questions
Exercise
● Map the orderitems table to an OrderItem
  class
● Get a list of all OrderItems

    –   Where they belong to order #3
    –   ... or the item name is “item 1”
    –   ... ordered by item name



(Now would be a good time to look at
tutorial_samples.py)
clear_mappers()
Creating, updating
o = Order()
o.user_id = 7
o.description = 'order 6'
session.add(o)
o.order_id is None
session.commit()
o.order_id == 6
o.description = 'order B'
session.commit()

session.delete(o)
session.commit()
Scoped (“smart”) sessions

Session = scoped_session(
    sessionmaker(autoflush=True, autocommit=False))

assert Session() == Session()
Scoped sessions 2

Base = declarative_base(metadata=Session.metadata)
class Order(Base): ...

o = Order()
o.user_id = 7
o.description = 'order 6'
session.commit()
Direct updates, deletes
SQL layer alert!
orders.update(orders.c.order_id==2).execute(isopen=1)

orders.delete(orders.c.order_id==2).execute()
One-to-many relations

class User(Base):
    orders = relation(Order, order_by=[Order.order_id])

u = session.query(User).first()
print u.orders
Editing collections
o = Order(description='An order')
u.orders.append(o)
session.commit()
Why sessions are your friends
Some ORMs rely on explicit save
u = User.get(1)
u.orders[0].description = 'An order'
u.save() # not real SA code
# doh! orders[0] was not saved!

More convenient, less error-prone to let ORM
track dirty objects
Identity map
Rows with same PK get mapped to same
object (per-session)
Limited caching for get()
Only for get()
Managing the identity map


sesion.query(cls).populate_existing()
session.expire(obj)
session.refresh(obj)
session.expunge(obj)
expunge_all, expire_all
Questions
Exercise
Load the user named 'jack' (lowercase)
Remove his first order
Save changes to the db
Fun with collections
u = session.query(User).filter_by(name='jack').one()
u.orders = u.orders[1:]
session.commit()

>>> session.query(Order).get(1)
Order(order_id=1,user_id=None,...)
Two solutions

o = u.orders[0]
>>> o
Order(order_id=1,user_id=7,description=u'order 1',isopen=0)

session.delete(o)
session.commit()

>>> u.orders
[Order(order_id=3,...), Order(order_id=5,...)]


 Why does it make sense for this to work
  differently than the previous example?
#2: delete-orphan
class User(Base):
    __table__ = users
    orders = relation(Order,
                      cascade="all, delete-orphan",
                      order_by=[Order.order_id])




u = session.query(User).get(7)
u.orders = u.orders[1:]
session.commit()

>>> session.query(Order).get(1) is None
True
Questions
Exercise

def user_for_order(order):
    session = Session.object_session(order)
    return ?
Backrefs

class User(Base):
    __table__ = users
    orders = relation(Order,
                      backref='user',
                      order_by=[orders.c.order_id])

o = session.query(Order).first()
o.user
That's it for fundamentals
Multi-object queries
One-to-one
Many-to-many
Relation queries
Eager/lazy loading
Transactions
Extensions and related projects
Exercise
List all users who have open orders (isopen is
nonzero)
A taste of advanced querying
All orders with an open order:

q = session.query(User).join(User.orders)

q.filter(Order.isopen==1).all()
Selecting multiple classes
What if we want the user and the order?
(efficiently)
q = session.query(User, Order) # cartesian join!

q = q.join(User.orders)
# or!
q = q.filter(User.user_id==Order.user_id)

u, o = q.filter(Order.isopen==1).first()
Dropping down to SQL

sql = """
select u.*
from users u
where u.user_id in (
    select user_id from orders where isopen = 1)
"""
session.query(User).from_statement(sql)


sql = """
select u.*, o.*
from users u join orders o on (u.user_id = o.user_id)
where o.isopen = 1
"""
session.query(User, Order).from_statement(sql)
Dropping down a little less

q = session.query(User, Order)
q = q.join(User.orders)
q.filter("orders.isopen = 1").all()
Exercise
In a single query, select the users and orders
where the order description is like 'order%'
One to one

class Address(Base):
    __table__ = addresses

class User(Base):
    orders = relation(Order,
                      order_by=[orders.c.order_id])
    address = relation(Address)




How does SQLA know to treat these
 differently?
Many to many

class Keyword(Base):
    __table__ = keywords

class Item(Base):
    __table__ = orderitems
    keywords = relation(Keyword, secondary=itemkeywords)
Relation queries

user = session.query(User).get(7)

q = session.query(Order)
q.filter(Order.user==user).all()
# q.filter(Order.user_id==user.user_id).all()
Relation queries 2

q = session.query(Order)

q.filter(Order.user.has(name='jack')).all()
q.filter(Order.user.has((User.name=='jack')
                        | (User.user_id >= 9))).all()

# q.filter(Order.user_id==
    select([users.c.user_id], users.c.name=='jack')).all()
# q.filter(Order.user_id==
    select([users.c.user_id], (users.c.name=='jack')
                            | (users.c.user_id >= 9))).all()
Relation queries 3

q = session.query(User)

q.filter(User.orders.any(Order.isopen > 0)).all()
q.filter(User.orders.any(
           Order.description.like('order%'))).all()

# q.filter(User.user_id.in_(
    select([orders.c.user_id],
           orders.c.isopen > 0))).all()
# q.filter(User.user_id.in_(
    select([orders.c.user_id],
           orders.c.description.like('order%')))).all()
Relation queries 4
Just need a raw EXISTS clause? Use .any() or
.has() without extra parameters.
Relation queries 5


Keyword = session.query(Keyword).filter_by(name='red').one()
q = session.query(Item)

q.filter(Item.keywords.contains(keyword)).all()

# q.filter(Item.item_id.in_(
    select([itemkeywords.c.item_id],
           itemkeywords.c.keyword_id
             ==keyword.keyword_id))).all()
Exercise
Retrieve all users that do not have any orders.
Breathe Easy
That was our last exercise!
Eager loading

class User(Base):
    orders = relation(Order,
                      order_by=[orders.c.order_id],
                      lazy=False)

# or
q = session.query(User).options(eagerload('orders'))

# also lazyload, noload
Transactions are simple

●   session: autocommit=False
     –   this is the default
     –   commit() / rollback() manually
●   autocommit=True
     –   each flush() also commits
Other transaction features
●   begin_nested
●   manual transaction management at the
    Connection level
__init__
__init__ is for object creation, not loading
use @reconstructor
class Order(Base):
    __table__ = orders
    def __init__(self):
        self.foo = []

   @reconstructor
   def loaded(self):
       self.foo = []
Questions
Related projects
Migrate
FormAlchemy
SqlSoup
Elixir
z3c.sqlalchemy
Migrate

# one-time setup

migrate create path/to/upgradescripts "comment"

migrate manage dbmanage.py
--repository=path/to/upgradescripts –url=db-connection-
url

./dbmanage.py version_control


# repeat as necessary:

./dbmanage.py script_sql sqlite
# edit script

./dbmanage.py upgrade
FormAlchemy

order1 = session.query(Order).first()

from formalchemy import FieldSet
fs = FieldSet(order1)
print fs.render()
FormAlchemy, cont.

from formalchemy import Grid
orders = session.query(Order).all()
g = Grid(Order, orders)
print g.render()
SqlSoup

>>> from sqlalchemy.ext.sqlsoup import SqlSoup
>>> db = SqlSoup(metadata)

>>> db.users.filter(db.users.user_id < 10).all()
[MappedUsers(user_id=7,name='jack'),
MappedUsers(user_id=8,name='ed'),
MappedUsers(user_id=9,name='fred')]



>>> db.users.first()
MappedUsers(user_id=7,name='jack')
>>> _.orders
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MappedUsers' object has no attribute
'orders'
SqlSoup 2

>>> db.users.relate('orders', db.orders)

>>> db.users.first().orders
[MappedOrders(...)]

>>> db.users.filter(db.users.orders.any()).all()
[MappedUsers(...)]
SqlSoup 3

s = select([func.count('*')],
           users.c.user_id==orders.c.user_id,
           from_obj=[orders],
           scalar=True)
s2 = select([users,
s.label('order_count')]).alias('users_with_count')
db.users_with_count = db.map(s2)
Elixir

   class Person(Entity):
       has_field('name', Unicode)
       acts_as_taggable()

   ...
   some_person_instance.add_tag('cool')
   ...
   cool_people = Person.get_by_tag('cool')

http://cleverdevil.org/computing/52/
Resources
irc://irc.freenode.net/#sqlalchemy
SQLA mailing list
Migrate, FormAlchemy, Elixir
Final Questions

More Related Content

What's hot

Troubleshooting MySQL Performance add-ons
Troubleshooting MySQL Performance add-onsTroubleshooting MySQL Performance add-ons
Troubleshooting MySQL Performance add-onsSveta Smirnova
 
Magento 2 | Declarative schema
Magento 2 | Declarative schemaMagento 2 | Declarative schema
Magento 2 | Declarative schemaKiel Pykett
 
Developing for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLDeveloping for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLJohn David Duncan
 
Rapid prototyping search applications with solr
Rapid prototyping search applications with solrRapid prototyping search applications with solr
Rapid prototyping search applications with solrLucidworks (Archived)
 
SQLite in Adobe AIR
SQLite in Adobe AIRSQLite in Adobe AIR
SQLite in Adobe AIRPeter Elst
 
Introducción rápida a SQL
Introducción rápida a SQLIntroducción rápida a SQL
Introducción rápida a SQLCarlos Hernando
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189Mahmoud Samir Fayed
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with SolrErik Hatcher
 
DBD::SQLite
DBD::SQLiteDBD::SQLite
DBD::SQLitecharsbar
 
The enterprise manager command line interface2
The enterprise manager command line interface2The enterprise manager command line interface2
The enterprise manager command line interface2Kellyn Pot'Vin-Gorman
 
Building node.js applications with Database Jones
Building node.js applications with Database JonesBuilding node.js applications with Database Jones
Building node.js applications with Database JonesJohn David Duncan
 
The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84Mahmoud Samir Fayed
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6Technopark
 
Development and deployment analytical solutions using R and Python (in polish)
Development and deployment analytical solutions using R and Python (in polish)Development and deployment analytical solutions using R and Python (in polish)
Development and deployment analytical solutions using R and Python (in polish)WLOG Solutions
 
The Ring programming language version 1.5.2 book - Part 43 of 181
The Ring programming language version 1.5.2 book - Part 43 of 181The Ring programming language version 1.5.2 book - Part 43 of 181
The Ring programming language version 1.5.2 book - Part 43 of 181Mahmoud Samir Fayed
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6Technopark
 

What's hot (20)

Schemadoc
SchemadocSchemadoc
Schemadoc
 
Troubleshooting MySQL Performance add-ons
Troubleshooting MySQL Performance add-onsTroubleshooting MySQL Performance add-ons
Troubleshooting MySQL Performance add-ons
 
Mysql python
Mysql pythonMysql python
Mysql python
 
Mysql python
Mysql pythonMysql python
Mysql python
 
Magento 2 | Declarative schema
Magento 2 | Declarative schemaMagento 2 | Declarative schema
Magento 2 | Declarative schema
 
Developing for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLDeveloping for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQL
 
Rapid prototyping search applications with solr
Rapid prototyping search applications with solrRapid prototyping search applications with solr
Rapid prototyping search applications with solr
 
SQLite in Adobe AIR
SQLite in Adobe AIRSQLite in Adobe AIR
SQLite in Adobe AIR
 
Introducción rápida a SQL
Introducción rápida a SQLIntroducción rápida a SQL
Introducción rápida a SQL
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with Solr
 
DBD::SQLite
DBD::SQLiteDBD::SQLite
DBD::SQLite
 
PHP and Mysql
PHP and MysqlPHP and Mysql
PHP and Mysql
 
The enterprise manager command line interface2
The enterprise manager command line interface2The enterprise manager command line interface2
The enterprise manager command line interface2
 
Building node.js applications with Database Jones
Building node.js applications with Database JonesBuilding node.js applications with Database Jones
Building node.js applications with Database Jones
 
The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6
 
Development and deployment analytical solutions using R and Python (in polish)
Development and deployment analytical solutions using R and Python (in polish)Development and deployment analytical solutions using R and Python (in polish)
Development and deployment analytical solutions using R and Python (in polish)
 
The Ring programming language version 1.5.2 book - Part 43 of 181
The Ring programming language version 1.5.2 book - Part 43 of 181The Ring programming language version 1.5.2 book - Part 43 of 181
The Ring programming language version 1.5.2 book - Part 43 of 181
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6
 

Similar to PyCon 2010 SQLAlchemy tutorial

Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationBartosz Konieczny
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수용 최
 
Using Scala Slick at FortyTwo
Using Scala Slick at FortyTwoUsing Scala Slick at FortyTwo
Using Scala Slick at FortyTwoEishay Smith
 
Inside PyMongo - MongoNYC
Inside PyMongo - MongoNYCInside PyMongo - MongoNYC
Inside PyMongo - MongoNYCMike Dirolf
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTPMustafa TURAN
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRick Copeland
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksMongoDB
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to CeleryIdan Gazit
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196Mahmoud Samir Fayed
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsEleanor McHugh
 
Python Development (MongoSF)
Python Development (MongoSF)Python Development (MongoSF)
Python Development (MongoSF)Mike Dirolf
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF Luc Bors
 
Postgres can do THAT?
Postgres can do THAT?Postgres can do THAT?
Postgres can do THAT?alexbrasetvik
 
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxRubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxDr Nic Williams
 
Moving to the NoSQL side: MySQL JSON functions
 Moving to the NoSQL side: MySQL JSON functions Moving to the NoSQL side: MySQL JSON functions
Moving to the NoSQL side: MySQL JSON functionsSveta Smirnova
 

Similar to PyCon 2010 SQLAlchemy tutorial (20)

Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customization
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
 
Using Scala Slick at FortyTwo
Using Scala Slick at FortyTwoUsing Scala Slick at FortyTwo
Using Scala Slick at FortyTwo
 
Inside PyMongo - MongoNYC
Inside PyMongo - MongoNYCInside PyMongo - MongoNYC
Inside PyMongo - MongoNYC
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to Celery
 
How te bring common UI patterns to ADF
How te bring common UI patterns to ADFHow te bring common UI patterns to ADF
How te bring common UI patterns to ADF
 
Sql lite android
Sql lite androidSql lite android
Sql lite android
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
Python Development (MongoSF)
Python Development (MongoSF)Python Development (MongoSF)
Python Development (MongoSF)
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF
 
Polyglot parallelism
Polyglot parallelismPolyglot parallelism
Polyglot parallelism
 
Postgres can do THAT?
Postgres can do THAT?Postgres can do THAT?
Postgres can do THAT?
 
Slickdemo
SlickdemoSlickdemo
Slickdemo
 
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxRubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
 
Moving to the NoSQL side: MySQL JSON functions
 Moving to the NoSQL side: MySQL JSON functions Moving to the NoSQL side: MySQL JSON functions
Moving to the NoSQL side: MySQL JSON functions
 

More from jbellis

Five Lessons in Distributed Databases
Five Lessons  in Distributed DatabasesFive Lessons  in Distributed Databases
Five Lessons in Distributed Databasesjbellis
 
Data day texas: Cassandra and the Cloud
Data day texas: Cassandra and the CloudData day texas: Cassandra and the Cloud
Data day texas: Cassandra and the Cloudjbellis
 
Cassandra Summit 2015
Cassandra Summit 2015Cassandra Summit 2015
Cassandra Summit 2015jbellis
 
Cassandra summit keynote 2014
Cassandra summit keynote 2014Cassandra summit keynote 2014
Cassandra summit keynote 2014jbellis
 
Cassandra 2.1
Cassandra 2.1Cassandra 2.1
Cassandra 2.1jbellis
 
Tokyo cassandra conference 2014
Tokyo cassandra conference 2014Tokyo cassandra conference 2014
Tokyo cassandra conference 2014jbellis
 
Cassandra Summit EU 2013
Cassandra Summit EU 2013Cassandra Summit EU 2013
Cassandra Summit EU 2013jbellis
 
London + Dublin Cassandra 2.0
London + Dublin Cassandra 2.0London + Dublin Cassandra 2.0
London + Dublin Cassandra 2.0jbellis
 
Cassandra Summit 2013 Keynote
Cassandra Summit 2013 KeynoteCassandra Summit 2013 Keynote
Cassandra Summit 2013 Keynotejbellis
 
Cassandra at NoSql Matters 2012
Cassandra at NoSql Matters 2012Cassandra at NoSql Matters 2012
Cassandra at NoSql Matters 2012jbellis
 
Top five questions to ask when choosing a big data solution
Top five questions to ask when choosing a big data solutionTop five questions to ask when choosing a big data solution
Top five questions to ask when choosing a big data solutionjbellis
 
State of Cassandra 2012
State of Cassandra 2012State of Cassandra 2012
State of Cassandra 2012jbellis
 
Massively Scalable NoSQL with Apache Cassandra
Massively Scalable NoSQL with Apache CassandraMassively Scalable NoSQL with Apache Cassandra
Massively Scalable NoSQL with Apache Cassandrajbellis
 
Cassandra 1.1
Cassandra 1.1Cassandra 1.1
Cassandra 1.1jbellis
 
Pycon 2012 What Python can learn from Java
Pycon 2012 What Python can learn from JavaPycon 2012 What Python can learn from Java
Pycon 2012 What Python can learn from Javajbellis
 
Apache Cassandra: NoSQL in the enterprise
Apache Cassandra: NoSQL in the enterpriseApache Cassandra: NoSQL in the enterprise
Apache Cassandra: NoSQL in the enterprisejbellis
 
Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)
Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)
Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)jbellis
 
Cassandra at High Performance Transaction Systems 2011
Cassandra at High Performance Transaction Systems 2011Cassandra at High Performance Transaction Systems 2011
Cassandra at High Performance Transaction Systems 2011jbellis
 
Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)
Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)
Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)jbellis
 
What python can learn from java
What python can learn from javaWhat python can learn from java
What python can learn from javajbellis
 

More from jbellis (20)

Five Lessons in Distributed Databases
Five Lessons  in Distributed DatabasesFive Lessons  in Distributed Databases
Five Lessons in Distributed Databases
 
Data day texas: Cassandra and the Cloud
Data day texas: Cassandra and the CloudData day texas: Cassandra and the Cloud
Data day texas: Cassandra and the Cloud
 
Cassandra Summit 2015
Cassandra Summit 2015Cassandra Summit 2015
Cassandra Summit 2015
 
Cassandra summit keynote 2014
Cassandra summit keynote 2014Cassandra summit keynote 2014
Cassandra summit keynote 2014
 
Cassandra 2.1
Cassandra 2.1Cassandra 2.1
Cassandra 2.1
 
Tokyo cassandra conference 2014
Tokyo cassandra conference 2014Tokyo cassandra conference 2014
Tokyo cassandra conference 2014
 
Cassandra Summit EU 2013
Cassandra Summit EU 2013Cassandra Summit EU 2013
Cassandra Summit EU 2013
 
London + Dublin Cassandra 2.0
London + Dublin Cassandra 2.0London + Dublin Cassandra 2.0
London + Dublin Cassandra 2.0
 
Cassandra Summit 2013 Keynote
Cassandra Summit 2013 KeynoteCassandra Summit 2013 Keynote
Cassandra Summit 2013 Keynote
 
Cassandra at NoSql Matters 2012
Cassandra at NoSql Matters 2012Cassandra at NoSql Matters 2012
Cassandra at NoSql Matters 2012
 
Top five questions to ask when choosing a big data solution
Top five questions to ask when choosing a big data solutionTop five questions to ask when choosing a big data solution
Top five questions to ask when choosing a big data solution
 
State of Cassandra 2012
State of Cassandra 2012State of Cassandra 2012
State of Cassandra 2012
 
Massively Scalable NoSQL with Apache Cassandra
Massively Scalable NoSQL with Apache CassandraMassively Scalable NoSQL with Apache Cassandra
Massively Scalable NoSQL with Apache Cassandra
 
Cassandra 1.1
Cassandra 1.1Cassandra 1.1
Cassandra 1.1
 
Pycon 2012 What Python can learn from Java
Pycon 2012 What Python can learn from JavaPycon 2012 What Python can learn from Java
Pycon 2012 What Python can learn from Java
 
Apache Cassandra: NoSQL in the enterprise
Apache Cassandra: NoSQL in the enterpriseApache Cassandra: NoSQL in the enterprise
Apache Cassandra: NoSQL in the enterprise
 
Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)
Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)
Dealing with JVM limitations in Apache Cassandra (Fosdem 2012)
 
Cassandra at High Performance Transaction Systems 2011
Cassandra at High Performance Transaction Systems 2011Cassandra at High Performance Transaction Systems 2011
Cassandra at High Performance Transaction Systems 2011
 
Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)
Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)
Cassandra 1.0 and the future of big data (Cassandra Tokyo 2011)
 
What python can learn from java
What python can learn from javaWhat python can learn from java
What python can learn from java
 

Recently uploaded

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 

Recently uploaded (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 

PyCon 2010 SQLAlchemy tutorial

  • 1. Install ● Python 2.5 or 2.6 (or pysqlite for 2.4) ● SQLAlchemy 0.5 1. easy_install, if needed ● wget http://peak.telecommunity.com/dist/ez_setup.py ● python ez_setup.py 2. easy_install sqlalchemy==0.5.8 ● http://old.utahpython.org/sqla2010/
  • 2. Michael Bayer Michael Bayer is a software architect in New York City and is the creator of SQLAlchemy. http://techspot.zzzeek.org/ @zzzeek
  • 3. ORM 101 – the bad old days c = db.cursor() sql = "SELECT * FROM users WHERE name = %s" c.execute(sql, (name,)) user = User(*c.fetchone()) user.last_login_at = time.time() sql = "UPDATE users SET last_login_at = %s WHERE name = %s" c.execute(sql, (user.last_login_at, name0)) c.commit()
  • 4.
  • 5. ORM 101 – and there was light session = Session() user = session.query(User).filter(name=name).one() user.last_login_at = time.time() session.commit()
  • 6. The devil is in the details ● Compound WHERE clauses, subqueries, outer joins, sql functions, ... ● Eager/lazy loading ● Support for legacy schemas ● Inheritance ● Conceptual integrity ● Setup overhead ● Database support
  • 9.
  • 10. Tough love? “Disproving the myth of 'the best database layer is the one that makes the database invisible' is a primary philosophy of SA. If you don't want to deal with SQL, then there's little point to using a [relational] database in the first place.”
  • 11. Technical excellence ● PK: multi-column is fine; mutable is fine; any data type is fine; doesn't have to be named “id” http://blogs.ittoolbox.com/database/soup/archives/primary-keyvil-part-i-73 ● Recognizes all database defaults instead of allowing a few special cases like “created_at” ● Doesn't make up its own query language ● No XML ● Introspection or define-tables-in-Python ● Session/unit-of-work based ● Migrations
  • 13. Database dependence: a feature ● Performance – Functions, partial indexes, bitmap indexes, partitioning, replication, ... ● Features – Views, arrays, recursive joins, full-text searching, ... See also: http://powerpostgresql.com/Downloads/database_d
  • 14. Caching Beaker integration is an example w/ the 0.6 distribution (currently in beta)
  • 16. Today's agenda: fundamentals Data Mapper vs Active Record SA Fundamentals Mapping basics Queries Sessions & the identity map Relationship lifecycle Backrefs
  • 17. Agenda 2: More ORM details Multi-object queries One-to-one Many-to-many Relation queries Eager/lazy loading Transactions Extensions and related projects
  • 18. Agenda 3: Extensions and related projects Migrate FormAlchemy SqlSoup Elixir z3c.sqlalchemy
  • 19. Two ORM patterns Active Record Data Mapper
  • 22. SQLAlchemy supports both ● Declarative plugin for common simple situations ● Full data mapper power when you need it
  • 23. Tables for this tutorial users addresses orders orderitems keywords itemkeywords
  • 24. Tables users = Table('users', metadata, Column('user_id', Integer, primary_key = True), Column('name', String(40))) users = Table('users', metadata, autoload=True) users = Table('users', metadata, autoload=True, Column('name', String(40), default='Jonathan'))
  • 25.
  • 26. Legacy columns ack = Table('ACK110030', metadata, Column('ITMNUMBER', Integer, primary_key=True, key='id'), Column('MNFCENTERLC_I', Integer, ForeignKey('MFC43222.id'), key='manufacturing_center_id'), ...)
  • 27. Setup from scratch engine = create_engine('sqlite:///:memory:', echo=True) metadata = MetaData() metadata.bind = engine Session = sessionmaker(bind=engine) from sqlalchemy.ext.declarative import declarative_base Base = declarative_base()
  • 29. Table + mapped class together class Order(Base): __tablename__ = 'orders' order_id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey(users.c.user_id)) description = Column('description', String(50)) isopen = Column(Integer, ColumnDefault(1))
  • 30. Full data mapper pattern orders = Table('orders', metadata, Column('order_id', Integer, ...), Column('user_id', Integer, ForeignKey(users.c.user_id)), Column('description', String(50)), Column('isopen', Integer, ColumnDefault(1)), class Order(object): pass mapper(Order, orders)
  • 31. The way we will do mapping class Order(Base): __table__ = orders
  • 32. Querying session = Session() q = session.query(Order) print q .all .get .first, .one
  • 33. Query modification q = session.query(Order) .filter .filter_by .order_by [desc, asc] .limit, .offset
  • 34. Operators == >= <= > < ~ | & not_ or_ and_ in_ between like startswith endswith
  • 35. Some examples q = session.query(Order) q.filter_by(user_id=7).order_by(Order.isopen).first() q.filter(Order.description.like('order%')).all() q.filter((Order.user_id==7) | (Order.isopen==1)).all() q.filter(or_(Order.user_id==7, Order.isopen==1)).all()
  • 36. Slicing: limit/offset sugar q = session.query(Order) q.limit(1).offset(2) q[2:3]
  • 38. Exercise ● Map the orderitems table to an OrderItem class ● Get a list of all OrderItems – Where they belong to order #3 – ... or the item name is “item 1” – ... ordered by item name (Now would be a good time to look at tutorial_samples.py)
  • 40. Creating, updating o = Order() o.user_id = 7 o.description = 'order 6' session.add(o) o.order_id is None session.commit() o.order_id == 6 o.description = 'order B' session.commit() session.delete(o) session.commit()
  • 41. Scoped (“smart”) sessions Session = scoped_session( sessionmaker(autoflush=True, autocommit=False)) assert Session() == Session()
  • 42. Scoped sessions 2 Base = declarative_base(metadata=Session.metadata) class Order(Base): ... o = Order() o.user_id = 7 o.description = 'order 6' session.commit()
  • 43. Direct updates, deletes SQL layer alert! orders.update(orders.c.order_id==2).execute(isopen=1) orders.delete(orders.c.order_id==2).execute()
  • 44. One-to-many relations class User(Base): orders = relation(Order, order_by=[Order.order_id]) u = session.query(User).first() print u.orders
  • 45. Editing collections o = Order(description='An order') u.orders.append(o) session.commit()
  • 46. Why sessions are your friends Some ORMs rely on explicit save u = User.get(1) u.orders[0].description = 'An order' u.save() # not real SA code # doh! orders[0] was not saved! More convenient, less error-prone to let ORM track dirty objects
  • 47. Identity map Rows with same PK get mapped to same object (per-session) Limited caching for get() Only for get()
  • 48. Managing the identity map sesion.query(cls).populate_existing() session.expire(obj) session.refresh(obj) session.expunge(obj) expunge_all, expire_all
  • 50. Exercise Load the user named 'jack' (lowercase) Remove his first order Save changes to the db
  • 51. Fun with collections u = session.query(User).filter_by(name='jack').one() u.orders = u.orders[1:] session.commit() >>> session.query(Order).get(1) Order(order_id=1,user_id=None,...)
  • 52. Two solutions o = u.orders[0] >>> o Order(order_id=1,user_id=7,description=u'order 1',isopen=0) session.delete(o) session.commit() >>> u.orders [Order(order_id=3,...), Order(order_id=5,...)] Why does it make sense for this to work differently than the previous example?
  • 53. #2: delete-orphan class User(Base): __table__ = users orders = relation(Order, cascade="all, delete-orphan", order_by=[Order.order_id]) u = session.query(User).get(7) u.orders = u.orders[1:] session.commit() >>> session.query(Order).get(1) is None True
  • 55. Exercise def user_for_order(order): session = Session.object_session(order) return ?
  • 56. Backrefs class User(Base): __table__ = users orders = relation(Order, backref='user', order_by=[orders.c.order_id]) o = session.query(Order).first() o.user
  • 57. That's it for fundamentals Multi-object queries One-to-one Many-to-many Relation queries Eager/lazy loading Transactions Extensions and related projects
  • 58. Exercise List all users who have open orders (isopen is nonzero)
  • 59. A taste of advanced querying All orders with an open order: q = session.query(User).join(User.orders) q.filter(Order.isopen==1).all()
  • 60. Selecting multiple classes What if we want the user and the order? (efficiently) q = session.query(User, Order) # cartesian join! q = q.join(User.orders) # or! q = q.filter(User.user_id==Order.user_id) u, o = q.filter(Order.isopen==1).first()
  • 61. Dropping down to SQL sql = """ select u.* from users u where u.user_id in ( select user_id from orders where isopen = 1) """ session.query(User).from_statement(sql) sql = """ select u.*, o.* from users u join orders o on (u.user_id = o.user_id) where o.isopen = 1 """ session.query(User, Order).from_statement(sql)
  • 62. Dropping down a little less q = session.query(User, Order) q = q.join(User.orders) q.filter("orders.isopen = 1").all()
  • 63. Exercise In a single query, select the users and orders where the order description is like 'order%'
  • 64. One to one class Address(Base): __table__ = addresses class User(Base): orders = relation(Order, order_by=[orders.c.order_id]) address = relation(Address) How does SQLA know to treat these differently?
  • 65. Many to many class Keyword(Base): __table__ = keywords class Item(Base): __table__ = orderitems keywords = relation(Keyword, secondary=itemkeywords)
  • 66. Relation queries user = session.query(User).get(7) q = session.query(Order) q.filter(Order.user==user).all() # q.filter(Order.user_id==user.user_id).all()
  • 67. Relation queries 2 q = session.query(Order) q.filter(Order.user.has(name='jack')).all() q.filter(Order.user.has((User.name=='jack') | (User.user_id >= 9))).all() # q.filter(Order.user_id== select([users.c.user_id], users.c.name=='jack')).all() # q.filter(Order.user_id== select([users.c.user_id], (users.c.name=='jack') | (users.c.user_id >= 9))).all()
  • 68. Relation queries 3 q = session.query(User) q.filter(User.orders.any(Order.isopen > 0)).all() q.filter(User.orders.any( Order.description.like('order%'))).all() # q.filter(User.user_id.in_( select([orders.c.user_id], orders.c.isopen > 0))).all() # q.filter(User.user_id.in_( select([orders.c.user_id], orders.c.description.like('order%')))).all()
  • 69. Relation queries 4 Just need a raw EXISTS clause? Use .any() or .has() without extra parameters.
  • 70. Relation queries 5 Keyword = session.query(Keyword).filter_by(name='red').one() q = session.query(Item) q.filter(Item.keywords.contains(keyword)).all() # q.filter(Item.item_id.in_( select([itemkeywords.c.item_id], itemkeywords.c.keyword_id ==keyword.keyword_id))).all()
  • 71. Exercise Retrieve all users that do not have any orders.
  • 72. Breathe Easy That was our last exercise!
  • 73. Eager loading class User(Base): orders = relation(Order, order_by=[orders.c.order_id], lazy=False) # or q = session.query(User).options(eagerload('orders')) # also lazyload, noload
  • 74. Transactions are simple ● session: autocommit=False – this is the default – commit() / rollback() manually ● autocommit=True – each flush() also commits
  • 75. Other transaction features ● begin_nested ● manual transaction management at the Connection level
  • 76. __init__ __init__ is for object creation, not loading use @reconstructor class Order(Base): __table__ = orders def __init__(self): self.foo = [] @reconstructor def loaded(self): self.foo = []
  • 79. Migrate # one-time setup migrate create path/to/upgradescripts "comment" migrate manage dbmanage.py --repository=path/to/upgradescripts –url=db-connection- url ./dbmanage.py version_control # repeat as necessary: ./dbmanage.py script_sql sqlite # edit script ./dbmanage.py upgrade
  • 80. FormAlchemy order1 = session.query(Order).first() from formalchemy import FieldSet fs = FieldSet(order1) print fs.render()
  • 81. FormAlchemy, cont. from formalchemy import Grid orders = session.query(Order).all() g = Grid(Order, orders) print g.render()
  • 82. SqlSoup >>> from sqlalchemy.ext.sqlsoup import SqlSoup >>> db = SqlSoup(metadata) >>> db.users.filter(db.users.user_id < 10).all() [MappedUsers(user_id=7,name='jack'), MappedUsers(user_id=8,name='ed'), MappedUsers(user_id=9,name='fred')] >>> db.users.first() MappedUsers(user_id=7,name='jack') >>> _.orders Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'MappedUsers' object has no attribute 'orders'
  • 83. SqlSoup 2 >>> db.users.relate('orders', db.orders) >>> db.users.first().orders [MappedOrders(...)] >>> db.users.filter(db.users.orders.any()).all() [MappedUsers(...)]
  • 84. SqlSoup 3 s = select([func.count('*')], users.c.user_id==orders.c.user_id, from_obj=[orders], scalar=True) s2 = select([users, s.label('order_count')]).alias('users_with_count') db.users_with_count = db.map(s2)
  • 85. Elixir class Person(Entity): has_field('name', Unicode) acts_as_taggable() ... some_person_instance.add_tag('cool') ... cool_people = Person.get_by_tag('cool') http://cleverdevil.org/computing/52/