SlideShare a Scribd company logo
1 of 35
Download to read offline
SQLAlchemy and Elixir

Jonathan LaCour

http://cleverdevil.org
jonathan@cleverdevil.org
What is SQLAlchemy?

  “SQLAlchemy is the Python SQL toolkit and
  Object Relational Mapper that gives application
  developers the full power and flexibility of SQL.”
What is Elixir?

 “Elixir is a declarative layer on top of SQLAlchemy.
 It is a thin wrapper, which provides the ability to
 define model objects following the Active Record
 design pattern, and using a DSL syntax.”
Plan of Action

• SQLAlchemy Overview
   • Concepts
   • Example
• Elixir Overview
   • Concepts
   • Example
• Questions and Advanced Topics
SQLAlchemy Concepts	

• Engine
• MetaData
• Table
• Mapper
• Session
• Query
SQLAlchemy Concepts: Engine	

• Connection handling and pooling.
• Defines the “dialect” for database-specific translation.
• PostgreSQL, MySQL, Oracle, MS-SQL, Firebird, Informix, SQLite.


    # create an engine
    engine = create_engine('postgres://user:pass@host/database')

    # perform a query
    connection = engine.connect()
    result = connection.execute('select * from users')
    for row in result:
        print row['username'], row['email']

    # close the connection
    connection.close()
SQLAlchemy Concepts: MetaData	

• A collection of “schema items” like tables and indexes.
• Can be “bound” to an engine.



  # create a metadata and bind it to an already-created engine
  metadata = MetaData()
  metadata.bind = engine

  # issue CREATE statements for objects within this metadata
  metadata.create_all()
SQLAlchemy Concepts: Table	

• A table in your SQL database.
• Associated with a MetaData.
• Can perform SQL operations against tables.
• Can be “reflected” from existing schemas (autoload=True).


       users_table = Table('users', metadata,
           Column('id', Integer, primary_key=True),
           Column('username', Unicode(16), nullable=False),
           Column('email', Unicode(60)),
           Column('password', Unicode(20), nullable=False)
       )
SQLAlchemy Concepts: Table




      # insert a row into the users table
      users_table.insert().execute(
          username='cleverdevil',
          email='jonathan@cleverdevil.org',
          password='s3cr3tw0rd'
      )
SQLAlchemy Concepts: Table


 # select all rows from the users table
 rows = users_table.select().execute()
 for row in rows:
     print row['username'], row['email']

 # select certain rows from the users table
 clever_not_devil_rows = users_table.select(
     and_(users_table.c.username.like('%clever%'),
          not_(users_table.c.username.like('%devil%')))
 ).execute()
SQLAlchemy Concepts: Mapper

• Part of the Object Relational Mapper (ORM).
• Associates a table (or other “selectable” schema object) with a class.
• Defines relationships between objects.


         class User(object):
             def __init__(self, username, email, password):
                 self.username = username
                 self.email = email
                 self.password = password

         mapper(User, users_table)
SQLAlchemy Concepts: Session

• Part of the Object Relational Mapper (ORM).
• Represents a “Unit of Work” which is a collection of objects to be persisted.
• Objects are “saved” to a session, then “flushed” to the database.

            # create a session and a user object
            session = create_session()

            user = User()
            user.username = 'cleverdevil'
            user.email = 'jonathan@cleverdevil.org'
            user.password = 's3cr3tw0rd'

            # save the object to the session and flush it
            session.save(user)
            session.flush()
SQLAlchemy Concepts: Query

• Query objects used to fetch mapped objects from the database.
• Often created through a session.
• Generatively build select statements.



                 # create a query object for User class
                 query = session.query(User)
SQLAlchemy Concepts: Query



    # get all User objects from the database
    for user in query.all():
        print user.name, user.email

    # get a single User object from the database
    cleverdevil = query.get_by(username='cleverdevil')
SQLAlchemy Concepts: Query




     # get the top 5 users with "clever" but not
     # "devil" in their username in alphabetical order
     users = query.filter(
         User.c.username.like('%clever%')
     ).filter(
         ~User.c.username.like('%devil%')
     ).order_by(User.c.username).limit(5)
SQLAlchemy Example

• Weblog Software
• People write Articles
• Plan: Tables, Classes, Mappers
SQLAlchemy Example: Tables

metadata = MetaData()

person_table = Table('person', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', Unicode),
    Column('email', Unicode),
    Column('password', Unicode)
)

article_table = Table('article', metadata,
    Column('id', Integer, primary_key=True),
    Column('title', Unicode),
    Column('description', Unicode),
    Column('content', Unicode),
    Column('author_id', Integer, ForeignKey(person_table.c.id))
)
SQLAlchemy Example: Objects


class Person(object):
    def __init__(self, name=None, email=None, password=None):
        self.name = name
        self.email = email
        self.password = password

class Article(object):
    def __init__(self, title=None, description=None,
                 content=None, author=None):
        self.title = title
        self.description = description
        self.content = content
        self.author = author
SQLAlchemy Example: Mappers




       mapper(Person, person_table, properties={
           'articles' : relation(Article)
       })

       mapper(Article, article_table, properties={
           'author' : relation(Person)
       })
SQLAlchemy Example: Demonstration

# bind our metadata to an in-memory    # create a session and save the post, which
# sqlite database, and create tables   # will also save the dependant Person object
metadata.bind = 'sqlite:///'           session = create_session()
metadata.create_all()                  session.save(blog_post)
                                       session.flush()
# create a Person instance
jonathan = Person(                     # create another session and use it to query
    name='Jonathan'                    # for our just created instance
    email='jonathan@cleverdevil.org'   session = create_session()
    password='s3cr3t'                  query = session.query(Person)
)                                      jonathan = query.get_by(name='Jonathan')

create an Article instance             # walk through the object, printing out some
blog_post = Article(                   # properties, including related objects
    title='Some Blog Post',            print jonathan.name
    description='Some description',    print jonathan.articles[0].title
    content=Some content,              print jonathan.articles[0].author.name
    author=jonathan
)
SQLAlchemy: In Summary

• We have just scratched the surface: SQLAlchemy is amazingly powerful.
   • Polymorphic inheritance.
   • Complex relationships.
   • Mapping to arbitrary selectables.
   • Useful extensions.
   • Much, much more!
• Excellent SQL toolkit and connection handling.
• Extremely powerful optional ORM.
SQLAlchemy: Mike Bayer and Chuck Norris



   Mike Bayer is a robot built by a higher order
   of beings who think in relational algebra,
   and can bend space-time to give him 36-48
   hours of productive time in a single day.

   He doesn’t sleep, he just codes with his
   eyes closed.
Elixir: Design Patterns

• SQLAlchemy uses the “Data Mapper” design pattern
   • Classes and tables aren’t one-to-one.
   • Classes can be mapped to arbitrary selects.


• Elixir uses the “Active Record” design pattern.
   • Classes and tables are one-to-one.
   • Classes, tables, and mappers can be defined in one step.
   • Unlike some other “Active Record” ORMs, compound primary keys are
     supported!
Elixir Concepts: Entity

• Defines your class, table, and mapper in a single step.
• Uses an easy-to-read domain-specific language (DSL).




                 class User(Entity):
                     has_field('username', Unicode(16))
                     has_field('email', Unicode(60))
                     has_field('password', Unicode(20))
Elixir Example

• Weblog Software (again) – People write Articles
• Plan: define entities.

    class Person(Entity):
        has_field('name', Unicode)
        has_field('email', Unicode)
        has_field('password', Unicode)

         has_many('articles', of_kind='Article', inverse='author')

    class Article(Entity):
        has_field('title', Unicode)
        has_field('description', Unicode)
        has_field('content', Unicode)

         belongs_to('author', of_kind='Person', inverse='articles')
Elixir Example: Demonstration

# bind our metadata to an in-memory    # elixir automatically creates a threadlocal
# sqlite database, and create tables   # session for you using “SessionContext”
metadata.bind = 'sqlite:///'           objectstore.flush(); objectstore.clear()
metadata.create_all()
                                       # elixir provides a convenience function for
# create a Person instance             # getting query objects
jonathan = Person(                     query = Person.query()
    name='Jonathan'                    jonathan = query.get_by(name='Jonathan')
    email='jonathan@cleverdevil.org'
    password='s3cr3t'                  # walk through the object, printing out some
)                                      # properties, including related objects
                                       print jonathan.name
create an Article instance             print jonathan.articles[0].title
blog_post = Article(                   print jonathan.articles[0].author.name
    title='Some Blog Post',
    description='Some description',
    content=Some content,
    author=jonathan
)
Elixir vs. SQLAlchemy

• Lines of Code for Weblog Data Model
   • SQLAlchemy weighs in at 38 lines.
   • Elixir comes in at 16 lines.
   • Thats 58% less code.
• Sometimes you don’t need all the power of SQLAlchemy
• But Elixir is pretty powerful in its own right....
More Elixir: Events

• Watch for changes on your entities
• Decorators for before and after insert, update, and delete.

    from elixir import *
    from elixir.events import after_update

    class Article(Entity):
        has_field('title', Unicode)
        has_field('description', Unicode)
        has_field('content', Unicode)
        belongs_to('author', of_kind='Person', inverse='articles')

         @after_update
         def notify_author(self):
             print 'Notifying', self.author.email
             print ' -> article:', self.title, 'was updated'
More Elixir: Encryption

• Automatically encrypts and decrypts fields using Blowfish.


from elixir import *
from elixir.ext.encrypted import acts_as_encrypted

class Person(Entity):
    has_field('name', Unicode)
    has_field('email', Unicode)
    has_field('password', Unicode)

     has_many('articles', of_kind='Article', inverse='author')
     acts_as_encrypted(for_fields=['password'], with_secret='abc123')
More Elixir: Versioning

• Automatically tracks versions of your entities.
• Reverting, version comparison, timestamps, version numbers, after_revert event.

       from elixir import *
       from elixir.ext.versioned import *

       class Article(Entity):
           has_field('title', Unicode)
           has_field('description', Unicode)
           has_field('content', Unicode)
           belongs_to('author', of_kind='Person', inverse='articles')
           acts_as_versioned()

            @after_revert
            def notify_author(self):
                print 'Notifying', self.author.email
                print ' -> article:', self.title, 'was reverted'
More Elixir: Versioning

# loop through previous versions of an article, showing differences
article = Article.query().get_by(title='Some Post')
print 'Current version:', article.version, article.timestamp
for version in article.versions:
    print ' * Old version:', version.version, version.timestamp
    print '     - differences ->', article.compare_with(version)

# get the version of this article as of a date and time
version = article.get_as_of(timestamp)

# revert to previous version
article.revert()

# revert to specific version number
article.revert_to(2)
More Elixir: Associables

• Create common association patterns easily
• Examples: addressable, taggable.


 from elixir.ext.associable import *      # loop through the tags on an article
                                          for tag in article.tags:
 class Tag(Entity):                           print 'Article', article.title
     has_field('name', Unicode)               print ' -> tagged as', tag.name

 acts_as_taggable = associable(Tag)       # fetch articles that are tagged with a
                                          # certain tag
 class Article(Entity):                   python_posts = Article.select_by_tags(
     has_field('title', Unicode)              name='python'
     has_field('description', Unicode)    )
     has_field('content', Unicode)

     acts_as_taggable('tags')
More Elixir: Lower Level Operations

• Elixir is built on SQLAlchemy.
• You can always drop down to table objects.


             results = select(
                 [Person.c.email, Article.c.title],
                 and_(
                     Person.c.name == 'Jonathan',
                     Person.c.id==Article.c.author_id
                 )
             ).execute()

             person_rows = Person.table.select().execute()
Elixir: Summary

• Simplified layer on SQLAlchemy
   • Active Record instead of Data Mapper
   • Lower-level operations always available


• Cross-cutting functionality through Elixir Statements
   • Associable
   • Encryption
   • Versioning
   • Write your own!
Questions


   can_i_do_it_with_sqlalchemy = lambda it: ‘Yep’




               Elixir http://elixir.ematia.de
        SQLAlchemy http://sqlalchemy.org
    Jonathan LaCour http://cleverdevil.org

More Related Content

What's hot

Increase your quality and performance
Increase your quality and performanceIncrease your quality and performance
Increase your quality and performanceDusko Vesin
 
A Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NETA Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NETJames Johnson
 
SharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentialsSharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentialsMark Rackley
 
SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery EssentialsMark Rackley
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQueryZeeshan Khan
 
jQuery Fundamentals
jQuery FundamentalsjQuery Fundamentals
jQuery FundamentalsGil Fink
 
Dojo >= 1.7 Kickstart
Dojo >= 1.7  KickstartDojo >= 1.7  Kickstart
Dojo >= 1.7 KickstartHazem Saleh
 
J Query The Write Less Do More Javascript Library
J Query   The Write Less Do More Javascript LibraryJ Query   The Write Less Do More Javascript Library
J Query The Write Less Do More Javascript Libraryrsnarayanan
 
J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012ghnash
 
Cassandra intro
Cassandra introCassandra intro
Cassandra introAstrails
 
UIAutomation + Mechanic.js
UIAutomation + Mechanic.jsUIAutomation + Mechanic.js
UIAutomation + Mechanic.jsjaykz52
 
Drupal Entities - Emerging Patterns of Usage
Drupal Entities - Emerging Patterns of UsageDrupal Entities - Emerging Patterns of Usage
Drupal Entities - Emerging Patterns of UsageRonald Ashri
 
Drupal & javascript
Drupal & javascriptDrupal & javascript
Drupal & javascriptAlmog Baku
 

What's hot (20)

Increase your quality and performance
Increase your quality and performanceIncrease your quality and performance
Increase your quality and performance
 
A Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NETA Rich Web Experience with jQuery, Ajax and .NET
A Rich Web Experience with jQuery, Ajax and .NET
 
SharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentialsSharePoint Cincy 2012 - jQuery essentials
SharePoint Cincy 2012 - jQuery essentials
 
Jquery
JqueryJquery
Jquery
 
Jquery
JqueryJquery
Jquery
 
SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery Essentials
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
 
jQuery Fundamentals
jQuery FundamentalsjQuery Fundamentals
jQuery Fundamentals
 
Dojo >= 1.7 Kickstart
Dojo >= 1.7  KickstartDojo >= 1.7  Kickstart
Dojo >= 1.7 Kickstart
 
J Query The Write Less Do More Javascript Library
J Query   The Write Less Do More Javascript LibraryJ Query   The Write Less Do More Javascript Library
J Query The Write Less Do More Javascript Library
 
J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012
 
Jquery
JqueryJquery
Jquery
 
Cassandra intro
Cassandra introCassandra intro
Cassandra intro
 
jQuery
jQueryjQuery
jQuery
 
UIAutomation + Mechanic.js
UIAutomation + Mechanic.jsUIAutomation + Mechanic.js
UIAutomation + Mechanic.js
 
jQuery
jQueryjQuery
jQuery
 
Drupal Entities - Emerging Patterns of Usage
Drupal Entities - Emerging Patterns of UsageDrupal Entities - Emerging Patterns of Usage
Drupal Entities - Emerging Patterns of Usage
 
Drupal & javascript
Drupal & javascriptDrupal & javascript
Drupal & javascript
 
jQuery Introduction
jQuery IntroductionjQuery Introduction
jQuery Introduction
 
D3.js and SVG
D3.js and SVGD3.js and SVG
D3.js and SVG
 

Viewers also liked

Python postgre sql a wonderful wedding
Python postgre sql   a wonderful weddingPython postgre sql   a wonderful wedding
Python postgre sql a wonderful weddingStéphane Wirtel
 
RocketClub Moonwalker Program
RocketClub Moonwalker ProgramRocketClub Moonwalker Program
RocketClub Moonwalker ProgramPaul Chen
 
Le persone si incontrano all'Informagiovani
Le persone si incontrano all'InformagiovaniLe persone si incontrano all'Informagiovani
Le persone si incontrano all'InformagiovaniInformagiovani Ancona
 
Sales presentation
Sales presentationSales presentation
Sales presentationSteve Tee
 
TEDx - China: How Do You Shape The World's Most Misunderstood Brand?
TEDx - China: How Do You Shape The World's Most Misunderstood Brand?TEDx - China: How Do You Shape The World's Most Misunderstood Brand?
TEDx - China: How Do You Shape The World's Most Misunderstood Brand?Luke Lombe
 
Marx p rrevwebinarfinal8.15.12v6 (1)
Marx p rrevwebinarfinal8.15.12v6 (1)Marx p rrevwebinarfinal8.15.12v6 (1)
Marx p rrevwebinarfinal8.15.12v6 (1)Marx Communications
 
Grupna kupovina Beograd Srbija, Snizenje Beograd
Grupna kupovina Beograd Srbija, Snizenje BeogradGrupna kupovina Beograd Srbija, Snizenje Beograd
Grupna kupovina Beograd Srbija, Snizenje BeogradGrupna kupovina
 
Интерактивный урок по психологии
Интерактивный урок по психологииИнтерактивный урок по психологии
Интерактивный урок по психологииDelight2000
 
рекламное заболевание
рекламное заболеваниерекламное заболевание
рекламное заболеваниеAnna Stepnova
 
Edu 653 due may 12
Edu 653 due may 12Edu 653 due may 12
Edu 653 due may 12nbk76dr
 
Teeme Ära Maailmakoristus 2012
Teeme Ära Maailmakoristus 2012Teeme Ära Maailmakoristus 2012
Teeme Ära Maailmakoristus 2012Anneli Ohvril
 
бс хурал
бс хуралбс хурал
бс хуралCopy Mn
 

Viewers also liked (20)

Python postgre sql a wonderful wedding
Python postgre sql   a wonderful weddingPython postgre sql   a wonderful wedding
Python postgre sql a wonderful wedding
 
RocketClub Moonwalker Program
RocketClub Moonwalker ProgramRocketClub Moonwalker Program
RocketClub Moonwalker Program
 
Le persone si incontrano all'Informagiovani
Le persone si incontrano all'InformagiovaniLe persone si incontrano all'Informagiovani
Le persone si incontrano all'Informagiovani
 
CM
CMCM
CM
 
Sales presentation
Sales presentationSales presentation
Sales presentation
 
Explore ooty
Explore ootyExplore ooty
Explore ooty
 
TEDx - China: How Do You Shape The World's Most Misunderstood Brand?
TEDx - China: How Do You Shape The World's Most Misunderstood Brand?TEDx - China: How Do You Shape The World's Most Misunderstood Brand?
TEDx - China: How Do You Shape The World's Most Misunderstood Brand?
 
TIM's Cheat Sheet
TIM's Cheat SheetTIM's Cheat Sheet
TIM's Cheat Sheet
 
Marx p rrevwebinarfinal8.15.12v6 (1)
Marx p rrevwebinarfinal8.15.12v6 (1)Marx p rrevwebinarfinal8.15.12v6 (1)
Marx p rrevwebinarfinal8.15.12v6 (1)
 
My school 11
My school 11My school 11
My school 11
 
Grupna kupovina Beograd Srbija, Snizenje Beograd
Grupna kupovina Beograd Srbija, Snizenje BeogradGrupna kupovina Beograd Srbija, Snizenje Beograd
Grupna kupovina Beograd Srbija, Snizenje Beograd
 
Интерактивный урок по психологии
Интерактивный урок по психологииИнтерактивный урок по психологии
Интерактивный урок по психологии
 
Numbers
NumbersNumbers
Numbers
 
My school 9
My school 9My school 9
My school 9
 
рекламное заболевание
рекламное заболеваниерекламное заболевание
рекламное заболевание
 
Edu 653 due may 12
Edu 653 due may 12Edu 653 due may 12
Edu 653 due may 12
 
Teeme Ära Maailmakoristus 2012
Teeme Ära Maailmakoristus 2012Teeme Ära Maailmakoristus 2012
Teeme Ära Maailmakoristus 2012
 
E mail
E mailE mail
E mail
 
Sinalizacao nova
Sinalizacao novaSinalizacao nova
Sinalizacao nova
 
бс хурал
бс хуралбс хурал
бс хурал
 

Similar to Slides python elixir

PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemyInada Naoki
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialjbellis
 
Data Modelling Zone 2019 - data modelling and JSON
Data Modelling Zone 2019 - data modelling and JSONData Modelling Zone 2019 - data modelling and JSON
Data Modelling Zone 2019 - data modelling and JSONGeorge McGeachie
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationSociable
 
Quick Introduction to Sphinx and Thinking Sphinx
Quick Introduction to Sphinx and Thinking SphinxQuick Introduction to Sphinx and Thinking Sphinx
Quick Introduction to Sphinx and Thinking Sphinxhayesdavis
 
MongoDB at ZPUGDC
MongoDB at ZPUGDCMongoDB at ZPUGDC
MongoDB at ZPUGDCMike Dirolf
 
APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...
APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...
APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...apidays
 
JavaScript!
JavaScript!JavaScript!
JavaScript!RTigger
 
NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020Thodoris Bais
 
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...NoSQLmatters
 
fuser interface-development-using-jquery
fuser interface-development-using-jqueryfuser interface-development-using-jquery
fuser interface-development-using-jqueryKostas Mavridis
 
Building Apps with MongoDB
Building Apps with MongoDBBuilding Apps with MongoDB
Building Apps with MongoDBNate Abele
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 

Similar to Slides python elixir (20)

Real World MVC
Real World MVCReal World MVC
Real World MVC
 
Oop concepts in python
Oop concepts in pythonOop concepts in python
Oop concepts in python
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
 
Week3
Week3Week3
Week3
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorial
 
Hibernate
HibernateHibernate
Hibernate
 
Introduction to java and oop
Introduction to java and oopIntroduction to java and oop
Introduction to java and oop
 
Data Modelling Zone 2019 - data modelling and JSON
Data Modelling Zone 2019 - data modelling and JSONData Modelling Zone 2019 - data modelling and JSON
Data Modelling Zone 2019 - data modelling and JSON
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentation
 
Quick Introduction to Sphinx and Thinking Sphinx
Quick Introduction to Sphinx and Thinking SphinxQuick Introduction to Sphinx and Thinking Sphinx
Quick Introduction to Sphinx and Thinking Sphinx
 
MongoDB at ZPUGDC
MongoDB at ZPUGDCMongoDB at ZPUGDC
MongoDB at ZPUGDC
 
APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...
APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...
APIdays Paris 2018 - Building scalable, type-safe GraphQL servers from scratc...
 
JavaScript!
JavaScript!JavaScript!
JavaScript!
 
NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020
 
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
 
Local Storage
Local StorageLocal Storage
Local Storage
 
fuser interface-development-using-jquery
fuser interface-development-using-jqueryfuser interface-development-using-jquery
fuser interface-development-using-jquery
 
Building Apps with MongoDB
Building Apps with MongoDBBuilding Apps with MongoDB
Building Apps with MongoDB
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
Slickdemo
SlickdemoSlickdemo
Slickdemo
 

Slides python elixir

  • 1. SQLAlchemy and Elixir Jonathan LaCour http://cleverdevil.org jonathan@cleverdevil.org
  • 2. What is SQLAlchemy? “SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL.”
  • 3. What is Elixir? “Elixir is a declarative layer on top of SQLAlchemy. It is a thin wrapper, which provides the ability to define model objects following the Active Record design pattern, and using a DSL syntax.”
  • 4. Plan of Action • SQLAlchemy Overview • Concepts • Example • Elixir Overview • Concepts • Example • Questions and Advanced Topics
  • 5. SQLAlchemy Concepts • Engine • MetaData • Table • Mapper • Session • Query
  • 6. SQLAlchemy Concepts: Engine • Connection handling and pooling. • Defines the “dialect” for database-specific translation. • PostgreSQL, MySQL, Oracle, MS-SQL, Firebird, Informix, SQLite. # create an engine engine = create_engine('postgres://user:pass@host/database') # perform a query connection = engine.connect() result = connection.execute('select * from users') for row in result: print row['username'], row['email'] # close the connection connection.close()
  • 7. SQLAlchemy Concepts: MetaData • A collection of “schema items” like tables and indexes. • Can be “bound” to an engine. # create a metadata and bind it to an already-created engine metadata = MetaData() metadata.bind = engine # issue CREATE statements for objects within this metadata metadata.create_all()
  • 8. SQLAlchemy Concepts: Table • A table in your SQL database. • Associated with a MetaData. • Can perform SQL operations against tables. • Can be “reflected” from existing schemas (autoload=True). users_table = Table('users', metadata, Column('id', Integer, primary_key=True), Column('username', Unicode(16), nullable=False), Column('email', Unicode(60)), Column('password', Unicode(20), nullable=False) )
  • 9. SQLAlchemy Concepts: Table # insert a row into the users table users_table.insert().execute( username='cleverdevil', email='jonathan@cleverdevil.org', password='s3cr3tw0rd' )
  • 10. SQLAlchemy Concepts: Table # select all rows from the users table rows = users_table.select().execute() for row in rows: print row['username'], row['email'] # select certain rows from the users table clever_not_devil_rows = users_table.select( and_(users_table.c.username.like('%clever%'), not_(users_table.c.username.like('%devil%'))) ).execute()
  • 11. SQLAlchemy Concepts: Mapper • Part of the Object Relational Mapper (ORM). • Associates a table (or other “selectable” schema object) with a class. • Defines relationships between objects. class User(object): def __init__(self, username, email, password): self.username = username self.email = email self.password = password mapper(User, users_table)
  • 12. SQLAlchemy Concepts: Session • Part of the Object Relational Mapper (ORM). • Represents a “Unit of Work” which is a collection of objects to be persisted. • Objects are “saved” to a session, then “flushed” to the database. # create a session and a user object session = create_session() user = User() user.username = 'cleverdevil' user.email = 'jonathan@cleverdevil.org' user.password = 's3cr3tw0rd' # save the object to the session and flush it session.save(user) session.flush()
  • 13. SQLAlchemy Concepts: Query • Query objects used to fetch mapped objects from the database. • Often created through a session. • Generatively build select statements. # create a query object for User class query = session.query(User)
  • 14. SQLAlchemy Concepts: Query # get all User objects from the database for user in query.all(): print user.name, user.email # get a single User object from the database cleverdevil = query.get_by(username='cleverdevil')
  • 15. SQLAlchemy Concepts: Query # get the top 5 users with "clever" but not # "devil" in their username in alphabetical order users = query.filter( User.c.username.like('%clever%') ).filter( ~User.c.username.like('%devil%') ).order_by(User.c.username).limit(5)
  • 16. SQLAlchemy Example • Weblog Software • People write Articles • Plan: Tables, Classes, Mappers
  • 17. SQLAlchemy Example: Tables metadata = MetaData() person_table = Table('person', metadata, Column('id', Integer, primary_key=True), Column('name', Unicode), Column('email', Unicode), Column('password', Unicode) ) article_table = Table('article', metadata, Column('id', Integer, primary_key=True), Column('title', Unicode), Column('description', Unicode), Column('content', Unicode), Column('author_id', Integer, ForeignKey(person_table.c.id)) )
  • 18. SQLAlchemy Example: Objects class Person(object): def __init__(self, name=None, email=None, password=None): self.name = name self.email = email self.password = password class Article(object): def __init__(self, title=None, description=None, content=None, author=None): self.title = title self.description = description self.content = content self.author = author
  • 19. SQLAlchemy Example: Mappers mapper(Person, person_table, properties={ 'articles' : relation(Article) }) mapper(Article, article_table, properties={ 'author' : relation(Person) })
  • 20. SQLAlchemy Example: Demonstration # bind our metadata to an in-memory # create a session and save the post, which # sqlite database, and create tables # will also save the dependant Person object metadata.bind = 'sqlite:///' session = create_session() metadata.create_all() session.save(blog_post) session.flush() # create a Person instance jonathan = Person( # create another session and use it to query name='Jonathan' # for our just created instance email='jonathan@cleverdevil.org' session = create_session() password='s3cr3t' query = session.query(Person) ) jonathan = query.get_by(name='Jonathan') create an Article instance # walk through the object, printing out some blog_post = Article( # properties, including related objects title='Some Blog Post', print jonathan.name description='Some description', print jonathan.articles[0].title content=Some content, print jonathan.articles[0].author.name author=jonathan )
  • 21. SQLAlchemy: In Summary • We have just scratched the surface: SQLAlchemy is amazingly powerful. • Polymorphic inheritance. • Complex relationships. • Mapping to arbitrary selectables. • Useful extensions. • Much, much more! • Excellent SQL toolkit and connection handling. • Extremely powerful optional ORM.
  • 22. SQLAlchemy: Mike Bayer and Chuck Norris Mike Bayer is a robot built by a higher order of beings who think in relational algebra, and can bend space-time to give him 36-48 hours of productive time in a single day. He doesn’t sleep, he just codes with his eyes closed.
  • 23. Elixir: Design Patterns • SQLAlchemy uses the “Data Mapper” design pattern • Classes and tables aren’t one-to-one. • Classes can be mapped to arbitrary selects. • Elixir uses the “Active Record” design pattern. • Classes and tables are one-to-one. • Classes, tables, and mappers can be defined in one step. • Unlike some other “Active Record” ORMs, compound primary keys are supported!
  • 24. Elixir Concepts: Entity • Defines your class, table, and mapper in a single step. • Uses an easy-to-read domain-specific language (DSL). class User(Entity): has_field('username', Unicode(16)) has_field('email', Unicode(60)) has_field('password', Unicode(20))
  • 25. Elixir Example • Weblog Software (again) – People write Articles • Plan: define entities. class Person(Entity): has_field('name', Unicode) has_field('email', Unicode) has_field('password', Unicode) has_many('articles', of_kind='Article', inverse='author') class Article(Entity): has_field('title', Unicode) has_field('description', Unicode) has_field('content', Unicode) belongs_to('author', of_kind='Person', inverse='articles')
  • 26. Elixir Example: Demonstration # bind our metadata to an in-memory # elixir automatically creates a threadlocal # sqlite database, and create tables # session for you using “SessionContext” metadata.bind = 'sqlite:///' objectstore.flush(); objectstore.clear() metadata.create_all() # elixir provides a convenience function for # create a Person instance # getting query objects jonathan = Person( query = Person.query() name='Jonathan' jonathan = query.get_by(name='Jonathan') email='jonathan@cleverdevil.org' password='s3cr3t' # walk through the object, printing out some ) # properties, including related objects print jonathan.name create an Article instance print jonathan.articles[0].title blog_post = Article( print jonathan.articles[0].author.name title='Some Blog Post', description='Some description', content=Some content, author=jonathan )
  • 27. Elixir vs. SQLAlchemy • Lines of Code for Weblog Data Model • SQLAlchemy weighs in at 38 lines. • Elixir comes in at 16 lines. • Thats 58% less code. • Sometimes you don’t need all the power of SQLAlchemy • But Elixir is pretty powerful in its own right....
  • 28. More Elixir: Events • Watch for changes on your entities • Decorators for before and after insert, update, and delete. from elixir import * from elixir.events import after_update class Article(Entity): has_field('title', Unicode) has_field('description', Unicode) has_field('content', Unicode) belongs_to('author', of_kind='Person', inverse='articles') @after_update def notify_author(self): print 'Notifying', self.author.email print ' -> article:', self.title, 'was updated'
  • 29. More Elixir: Encryption • Automatically encrypts and decrypts fields using Blowfish. from elixir import * from elixir.ext.encrypted import acts_as_encrypted class Person(Entity): has_field('name', Unicode) has_field('email', Unicode) has_field('password', Unicode) has_many('articles', of_kind='Article', inverse='author') acts_as_encrypted(for_fields=['password'], with_secret='abc123')
  • 30. More Elixir: Versioning • Automatically tracks versions of your entities. • Reverting, version comparison, timestamps, version numbers, after_revert event. from elixir import * from elixir.ext.versioned import * class Article(Entity): has_field('title', Unicode) has_field('description', Unicode) has_field('content', Unicode) belongs_to('author', of_kind='Person', inverse='articles') acts_as_versioned() @after_revert def notify_author(self): print 'Notifying', self.author.email print ' -> article:', self.title, 'was reverted'
  • 31. More Elixir: Versioning # loop through previous versions of an article, showing differences article = Article.query().get_by(title='Some Post') print 'Current version:', article.version, article.timestamp for version in article.versions: print ' * Old version:', version.version, version.timestamp print ' - differences ->', article.compare_with(version) # get the version of this article as of a date and time version = article.get_as_of(timestamp) # revert to previous version article.revert() # revert to specific version number article.revert_to(2)
  • 32. More Elixir: Associables • Create common association patterns easily • Examples: addressable, taggable. from elixir.ext.associable import * # loop through the tags on an article for tag in article.tags: class Tag(Entity): print 'Article', article.title has_field('name', Unicode) print ' -> tagged as', tag.name acts_as_taggable = associable(Tag) # fetch articles that are tagged with a # certain tag class Article(Entity): python_posts = Article.select_by_tags( has_field('title', Unicode) name='python' has_field('description', Unicode) ) has_field('content', Unicode) acts_as_taggable('tags')
  • 33. More Elixir: Lower Level Operations • Elixir is built on SQLAlchemy. • You can always drop down to table objects. results = select( [Person.c.email, Article.c.title], and_( Person.c.name == 'Jonathan', Person.c.id==Article.c.author_id ) ).execute() person_rows = Person.table.select().execute()
  • 34. Elixir: Summary • Simplified layer on SQLAlchemy • Active Record instead of Data Mapper • Lower-level operations always available • Cross-cutting functionality through Elixir Statements • Associable • Encryption • Versioning • Write your own!
  • 35. Questions can_i_do_it_with_sqlalchemy = lambda it: ‘Yep’ Elixir http://elixir.ematia.de SQLAlchemy http://sqlalchemy.org Jonathan LaCour http://cleverdevil.org