SlideShare uma empresa Scribd logo
1 de 15
From SQLAlchemy to Ming with
       TurboGears2




          Alessandro Molina
      alessandro.molina@axant.it
             @__amol__
Simple, Stupid, Serviceable
●   We wanted to offer to development team
    members the opportunity to take a first look at
    MongoDB.
●   We wanted to do this by letting them write an
    actual web app using Python.
●   We wanted a real use case: “expenses and
    incomings” tracking (serviceable)
●   We wanted everyone to understand how it is
    expected to work (stupid)
●   Must be blazing fast to implement, we don't have
    a lot of time (simple)
Involved Technologies

      ●   Python → http://www.python.org
      ●   TurboGears2 → http://www.turbogears.org
      ●   SQLAlchemy → http://www.sqlalchemy.org
      ●   Ming → http://merciless.sourceforge.net/index.html
      ●   Genshi → http://genshi.edgewall.org
      ●   ToscaWidgets → http://toscawidgets.org
      ●   Sprox → http://www.sprox.org
Python Technologies
●   Why? Needed a WebApp ready in 5 minutes while being
    possible to quickly play with the code
●   Python: Our team is manly python developers based
●   TurboGears2: Our team is used to TG. Object Dispatch is really
    comfortable and the framework is incredibly fast to start with
    while still making possible to quickly get under the hood.
●   Genshi: clean and plain xhtml, even designers can understand it,
    also it came by default
●   ToscaWidgets: Can do most of the HTML for us
●   Sprox: Can do most of the CRUD for us
Quickstarting Our Project
                        (tg2dev)Quasar-2:tuts amol$ paster quickstart mt_sqla
●   Project Structure   Enter package name [mt_sqla]: paster quickstart mt_sqla
                         (tg2dev)Quasar-2:tuts amol$
                         Enter package name [mt_sqla]:
                        Would you prefer mako templates? (yes/[no]):
                        Do you need prefer mako templates? (yes/[no]):
                         Would you authentication and authorization in this project? ([yes]/no):

    with Controllers    Selected need implied templates: authorization in this project? ([yes]/no):
                         Do you and authentication and
                         Selected and implied templates:
                          tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template
                           tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template

    for Index Page      (tg2dev)Quasar-2:mt-sqla amol$ python setup.py develop
                         (tg2dev)Quasar-2:mt-sqla amol$ python setup.py develop
                        paster srunning develop
                         paster srunning develop
                        Installed /Users/amol/wrk/tuts/mt-sqla
                         Installed /Users/amol/wrk/tuts/mt-sqla

●   Models for Users,   (tg2dev)Quasar-2:mt-sqla amol$ paster setup-app development.ini
                         (tg2dev)Quasar-2:mt-sqla amol$ paster setup-app development.ini
                        Running setup_config() from mt_sqla.websetup
                         Running setup_config() from mt_sqla.websetup
                            Creating tables

    Groups and
                             Creating tables
                        (tg2dev)Quasar-2:mt-sqla amol$ paster serve development.ini
                         (tg2dev)Quasar-2:mt-sqla amol$ paster serve development.ini
                        Starting server in PID 23939.

    Permission
                        serving on server in PID 23939.
                         Starting http://127.0.0.1:8080
                         serving on http://127.0.0.1:8080




●   Authentication      (tg2dev)Quasar-2:tuts amol$ paster quickstart –ming mt_ming
                        Enter package name [mt_ming]: paster quickstart –ming mt_ming
                         (tg2dev)Quasar-2:tuts amol$
                         Enter package name [mt_ming]:

    and Authorization
                        Would you prefer mako templates? (yes/[no]):
                        Do you need prefer mako templates? (yes/[no]):
                         Would you authentication and authorization in this project? ([yes]/no):
                        Selected need implied templates: authorization in this project? ([yes]/no):
                         Do you and authentication and
                         Selected and implied templates:
                          tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template
                           tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template

●   Both on SQLA        (tg2dev)Quasar-2:mt-ming amol$ python setup.py develop
                         (tg2dev)Quasar-2:mt-ming amol$ python setup.py develop
                        paster srunning develop
                         paster srunning develop
                        Installed /Users/amol/wrk/tuts/mt-ming

    and Ming
                         Installed /Users/amol/wrk/tuts/mt-ming
                        (tg2dev)Quasar-2:mt-ming amol$ paster setup-app development.ini
                         (tg2dev)Quasar-2:mt-ming amol$ paster setup-app development.ini
                        Running setup_app() from mt_ming.websetup
                         Running setup_app() from mt_ming.websetup
                        (tg2dev)Quasar-2:mt-ming amol$ paster serve development.ini
                         (tg2dev)Quasar-2:mt-ming amol$ paster serve development.ini
                        Starting server in PID 23939.
                        serving on server in PID 23939.
                         Starting http://127.0.0.1:8080
                         serving on http://127.0.0.1:8080
Overview

               Browser                      Genshi




                                         ToscaWidgets
              TurboGears




             Controller Code            Sprox (TGAdmin)




      Ming                 SQLAlchemy
SQLAlchemy
●   Supports pratically everything: PostgresSQL,
    MySQL, SQLite, Firebird, Oracle, MSSQL, Sybase,
    DB2, Informix, SAPDB, MSAccess
●   Declarative ORM layer with access to a powerful and
    flexible query builder
●   Unlike many tools, it never enforces schemas or
    relies on naming conventions of any kind.
●   Unit Of Work system organizes pending
    insert/update/delete operations into queues and
    flushes them all in one batch (Patterns of Enterprise
    Application Architecture - Martin Fowler)
Python MongoDB Ecosystem
  ●   PyMongo: Driver for MongoDB, everything is a dictionary
  ●   MongoEngine: ORM, query language is familiar to Django users
  ●   Ming: ORM, query language is familiar to SQLAlchemy users
  ●   MongoKit: ORM, written to be as simple and light as possible

MongoKit                                              Ming
class BlogPost(Document):                             class WikiComment(MappedClass):
    structure = {                                         class __mongometa__:
        'title':unicode,                                      session = session
        'body':unicode,                                       name = 'wiki_comment'
        'author':unicode,
        'date_creation':datetime.datetime,                _id = FieldProperty(schema.ObjectId)
        'rank':int                                        text=FieldProperty(str, if_missing='')
    }                                                     page_id = ForeignIdProperty('WikiPage')
                                                          page=RelationProperty('WikiPage')
tutorial.BlogPost.find({'body': {'$exists': True}})
                                                      WikiComment.query.find({'text':{'$exists':True}})


MongoEngine                                           PyMongo
class User(Document):                                 post = {"author": "Mike",
    email = StringField(required=True)                ...     "text": "My first blog post!",
    first_name = StringField(max_length=50)           ...     "tags": ["mongodb", "python"],
    last_name = StringField(max_length=50)            ...     "date": datetime.datetime.utcnow()}

Users.objects(age__lte=18)                            db.posts.find({"author": "Mike"})
Ming
●   SQLAlchemy inspired, easy to catch up if you are
    used to SQLAlchemy
●   Declarative ORM layer, use ORM through objects
    and get direct access to mongo through collections
●   Integrated Migrations (deprecated attributes and
    even on-demand lazy migration code)
●   Unit of Work, we tried it, we loved it, we wanted it
    even on MongoDB
●   Mongo In Memory, complete implementation of
    MongoDB in memory for unit testing
Some Little Magic (TGAdmin)




●   It did CRUD for us.
●   Works both with SQLAlchemy and Ming
●   Comes for free with TurboGears2
●   Sprox based, deeply customizable
Storing our Data
from sqlalchemy import Table, Column                  from ming import schema as s
 from sqlalchemy import Table, Column
from sqlalchemy.types import Unicode, Integer,         from ming import schema as s
                                                      from ming.orm import FieldProperty, Mapper
Float, sqlalchemy.types import Unicode, Integer,
 from DateTime                                         from ming.orm import FieldProperty, Mapper
                                                      from ming.orm.declarative import MappedClass
 Float, DateTime
from datetime import datetime                          from ming.orm.declarative import MappedClass
                                                      from session import DBSession
 from datetime import datetime                         from session import DBSession
                                                      from datetime import datetime
                                                       from datetime import datetime
class MoneyTransfer(DeclarativeBase):                 class MoneyTransfer(MappedClass):
 class MoneyTransfer(DeclarativeBase):
    __tablename__ = 'money_transfers'                  class MoneyTransfer(MappedClass):
                                                          class __mongometa__:
     __tablename__ = 'money_transfers'                     class __mongometa__:
                                                              session = DBSession
                                                               session = DBSession
                                                              name = 'money_transfers'
                                                               name = 'money_transfers'
    uid = Column(Integer, autoincrement=True,            _id = FieldProperty(s.ObjectId)
     uid = Column(Integer,primary_key=True)
                            autoincrement=True,           _id = FieldProperty(s.ObjectId)
                                                         date = FieldProperty(s.DateTime,
                            primary_key=True)
    date = Column(DateTime, default=datetime.now)         date = FieldProperty(s.DateTime,
                                                                              if_missing=datetime.now)
    sign = =Column(Integer, default=1)
     date    Column(DateTime, default=datetime.now)                            if_missing=datetime.now)
                                                         sign = FieldProperty(s.Int, if_missing=1)
     sign = Column(Integer, default=1)
    description = Column(Unicode(255))                    sign = FieldProperty(s.Int, if_missing=1)
                                                         description = FieldProperty(s.String)
     description = Column(Unicode(255))
    value = Column(Float, default=0)                      description = FieldProperty(s.String)
                                                         value = FieldProperty(s.Float, if_missing=0)
     value = Column(Float, default=0)                     value = FieldProperty(s.Float, if_missing=0)
Retrieving and Displaying Data
from tw.forms import DataGrid                                  from tw.forms import DataGrid
from tw.forms.datagrid DataGrid
 from tw.forms import import Column                            from tw.forms.datagrid DataGrid
                                                                from tw.forms import import Column
 from tw.forms.datagrid import Column                           from tw.forms.datagrid import Column
transactions_grid = DataGrid(fields=[                          transactions_grid = DataGrid(fields=[
 transactions_grid 'date'),
    Column('Date', = DataGrid(fields=[                          transactions_grid 'date'),
                                                                   Column('Date', = DataGrid(fields=[
     Column('Date', 'date'),
    Column('Description', 'description'),                           Column('Date', 'date'),
                                                                   Column('Description', 'description'),
     Column('Description', 'description'),
    Column('Value', lambda row:row.value*row.sign)])                Column('Description', 'description'),
                                                                   Column('Value', lambda row:row.value*row.sign)])
     Column('Value', lambda row:row.value*row.sign)])               Column('Value', lambda row:row.value*row.sign)])
class RootController(BaseController):                          class RootController(BaseController):
 class RootController(BaseController):
    @expose('mt_sqla.templates.index')                          class RootController(BaseController):
                                                                   @expose('mt_ming.templates.index')
     @expose('mt_sqla.templates.index')
    def index(self):                                                @expose('mt_ming.templates.index')
                                                                   def index(self):
     def index(self): DBSession.query(MoneyTransfer).all()
        transactions =                                              def index(self): MoneyTransfer.query.find().all()
                                                                       transactions =
         transactions = DBSession.query(MoneyTransfer).all()
        total = sum((t.value*t.sign for t in transactions))             transactions = MoneyTransfer.query.find().all()
                                                                       total = sum((t.value*t.sign for t in transactions))
         total = sum((t.value*t.sign for t in transactions))
        return dict(page='index',                                       total = sum((t.value*t.sign for t in transactions))
                                                                       return dict(page='index',
         return dict(page='index',
                     transactions=transactions,                         return dict(page='index',
                                                                                    transactions=transactions,
                      transactions=transactions,
                     transactions_grid=transactions_grid,                            transactions=transactions,
                                                                                    transactions_grid=transactions_grid,
                      transactions_grid=transactions_grid,
                     total=total)                                                    transactions_grid=transactions_grid,
                                                                                    total=total)
                      total=total)                                                   total=total)




         <div style="width:650px; margin-top:20px;">
          <div style="width:650px; margin-top:20px;">
             <a href="${tg.url('/admin/moneytransfers/new')}">Add New Transaction</a>
              <a href="${tg.url('/admin/moneytransfers/new')}">Add New Transaction</a>
             ${transactions_grid(transactions)}
              ${transactions_grid(transactions)}
             <div style="text-align:right;"><strong>AVAILABLE:</strong> ${total}</div>
              <div style="text-align:right;"><strong>AVAILABLE:</strong> ${total}</div>
         </div>
          </div>
What changed
●   Template remained the same. Thanks god we
    have an ORM.
●   Had to change the model.
●   Had to change just 1 line of controller code to
    retrieve the data. Ming and SQLA are similar
    enough
●   Did we really need to change that line? We just
    want to get a list of objects...
Sprox, abstraction over abstraction
   ●   ORMProvider, provides an abstraction over the ORM
   ●   ORMProviderSelector, automatically detects the provider to
       use from a model.
   ●   Mix those together and you have a db independent layer.
        ●   Provider.query(self, entity, limit=None, offset=0, limit_fields=None,
            order_by=None, desc=False) → get all objects of a collection
        ●   Provider.get_obj(self, entity, params) → get an object
        ●   Provider.update(self, entity, params) → update an object
        ●   Provider.create(self, entity, params) → create a new object
SQLAlchemy
transactions = DBSession.query(MoneyTransfer).all()
 transactions = DBSession.query(MoneyTransfer).all()
                                                       Sprox
                                                       count, transactions = provider.query(MoneyTransfer)
Ming                                                    count, transactions = provider.query(MoneyTransfer)

transactions = MoneyTransfer.query.find().all()
 transactions = MoneyTransfer.query.find().all()
Experiments Experience

●   Starting with a really simple use case made people
    get comfortable with MongoDB and feel confident
    enough to start learning more complex features.
●   The idea of being possible to use sprox to abstract
    over the db, making possible to switch back anytime,
    created a “safety net” idea in people.
●   When people feel safe they start experimenting a lot
    more and learn by themselves.

Mais conteúdo relacionado

Mais procurados

FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Supercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamicSupercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamicIan Robertson
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRJavier Abadía
 
Python在豆瓣的应用
Python在豆瓣的应用Python在豆瓣的应用
Python在豆瓣的应用Qiangning Hong
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsTimur Shemsedinov
 
JavaScript 101
JavaScript 101JavaScript 101
JavaScript 101ygv2000
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesDragos Ionita
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksMongoDB
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboyKenneth Geisshirt
 
This upload requires better support for ODP format
This upload requires better support for ODP formatThis upload requires better support for ODP format
This upload requires better support for ODP formatForest Mars
 
Building High Performance Web Applications and Sites
Building High Performance Web Applications and SitesBuilding High Performance Web Applications and Sites
Building High Performance Web Applications and Sitesgoodfriday
 
Dgeni documentation generator
Dgeni   documentation generatorDgeni   documentation generator
Dgeni documentation generatorPeter Darwin
 
Introduction to Grails Framework
Introduction to Grails FrameworkIntroduction to Grails Framework
Introduction to Grails FrameworkPT.JUG
 
All you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopAll you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopSaša Tatar
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2Jeado Ko
 
Svcc Building Rich Applications with Groovy's SwingBuilder
Svcc Building Rich Applications with Groovy's SwingBuilderSvcc Building Rich Applications with Groovy's SwingBuilder
Svcc Building Rich Applications with Groovy's SwingBuilderAndres Almiray
 

Mais procurados (20)

Es.next
Es.nextEs.next
Es.next
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Supercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamicSupercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamic
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
Python在豆瓣的应用
Python在豆瓣的应用Python在豆瓣的应用
Python在豆瓣的应用
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
 
JavaScript 101
JavaScript 101JavaScript 101
JavaScript 101
 
The State of JavaScript
The State of JavaScriptThe State of JavaScript
The State of JavaScript
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best Practices
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboy
 
V8
V8V8
V8
 
This upload requires better support for ODP format
This upload requires better support for ODP formatThis upload requires better support for ODP format
This upload requires better support for ODP format
 
Building High Performance Web Applications and Sites
Building High Performance Web Applications and SitesBuilding High Performance Web Applications and Sites
Building High Performance Web Applications and Sites
 
Dgeni documentation generator
Dgeni   documentation generatorDgeni   documentation generator
Dgeni documentation generator
 
Introduction to Grails Framework
Introduction to Grails FrameworkIntroduction to Grails Framework
Introduction to Grails Framework
 
All you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopAll you need to know about the JavaScript event loop
All you need to know about the JavaScript event loop
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2
 
Svcc Building Rich Applications with Groovy's SwingBuilder
Svcc Building Rich Applications with Groovy's SwingBuilderSvcc Building Rich Applications with Groovy's SwingBuilder
Svcc Building Rich Applications with Groovy's SwingBuilder
 

Semelhante a From SQLAlchemy to Ming with TurboGears2

Native Java with GraalVM
Native Java with GraalVMNative Java with GraalVM
Native Java with GraalVMSylvain Wallez
 
Get together on getting more out of typescript &amp; angular 2
Get together on getting more out of typescript &amp; angular 2Get together on getting more out of typescript &amp; angular 2
Get together on getting more out of typescript &amp; angular 2Ruben Haeck
 
Dynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web siteDynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web siteSriram Natarajan
 
TypeScript for Java Developers
TypeScript for Java DevelopersTypeScript for Java Developers
TypeScript for Java DevelopersYakov Fain
 
Robust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time ChecksRobust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time ChecksStoyan Nikolov
 
WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows
WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows
WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows T.Rob Wyatt
 
L Fu - Dao: a novel programming language for bioinformatics
L Fu - Dao: a novel programming language for bioinformaticsL Fu - Dao: a novel programming language for bioinformatics
L Fu - Dao: a novel programming language for bioinformaticsJan Aerts
 
Why you should be using structured logs
Why you should be using structured logsWhy you should be using structured logs
Why you should be using structured logsStefan Krawczyk
 
Writing Apps with HotCocoa and MacRuby
Writing Apps with HotCocoa and MacRubyWriting Apps with HotCocoa and MacRuby
Writing Apps with HotCocoa and MacRubyRenzo Borgatti
 
Monitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTapMonitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTapPadraig O'Sullivan
 
Ember-CLI Blueprints for fun and profit
Ember-CLI Blueprints for fun and profitEmber-CLI Blueprints for fun and profit
Ember-CLI Blueprints for fun and profitSalesforce Engineering
 
CDK Meetup: Rule the World through IaC
CDK Meetup: Rule the World through IaCCDK Meetup: Rule the World through IaC
CDK Meetup: Rule the World through IaCsmalltown
 
Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...
Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...
Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...Amazon Web Services
 
E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)
E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)
E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)Valeriy Kravchuk
 
End to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaEnd to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaBabacar NIANG
 
idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...
idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...
idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...idsecconf
 
What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)
What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)
What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)Igalia
 
BarcelonaJUG2016: walkmod: how to run and design code transformations
BarcelonaJUG2016: walkmod: how to run and design code transformationsBarcelonaJUG2016: walkmod: how to run and design code transformations
BarcelonaJUG2016: walkmod: how to run and design code transformationswalkmod
 

Semelhante a From SQLAlchemy to Ming with TurboGears2 (20)

Native Java with GraalVM
Native Java with GraalVMNative Java with GraalVM
Native Java with GraalVM
 
Get together on getting more out of typescript &amp; angular 2
Get together on getting more out of typescript &amp; angular 2Get together on getting more out of typescript &amp; angular 2
Get together on getting more out of typescript &amp; angular 2
 
Dynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web siteDynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web site
 
TypeScript for Java Developers
TypeScript for Java DevelopersTypeScript for Java Developers
TypeScript for Java Developers
 
Robust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time ChecksRobust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time Checks
 
WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows
WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows
WMQ Toolbox: 20 Scripts, One-liners, & Utilities for UNIX & Windows
 
L Fu - Dao: a novel programming language for bioinformatics
L Fu - Dao: a novel programming language for bioinformaticsL Fu - Dao: a novel programming language for bioinformatics
L Fu - Dao: a novel programming language for bioinformatics
 
Why you should be using structured logs
Why you should be using structured logsWhy you should be using structured logs
Why you should be using structured logs
 
Writing Apps with HotCocoa and MacRuby
Writing Apps with HotCocoa and MacRubyWriting Apps with HotCocoa and MacRuby
Writing Apps with HotCocoa and MacRuby
 
Django tricks (2)
Django tricks (2)Django tricks (2)
Django tricks (2)
 
Monitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTapMonitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTap
 
Ember-CLI Blueprints for fun and profit
Ember-CLI Blueprints for fun and profitEmber-CLI Blueprints for fun and profit
Ember-CLI Blueprints for fun and profit
 
CDK Meetup: Rule the World through IaC
CDK Meetup: Rule the World through IaCCDK Meetup: Rule the World through IaC
CDK Meetup: Rule the World through IaC
 
Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...
Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...
Monitoring as Code: Getting to Monitoring-Driven Development - DEV314 - re:In...
 
E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)
E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)
E bpf and dynamic tracing for mariadb db as (mariadb day during fosdem 2020)
 
End to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaEnd to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux Saga
 
idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...
idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...
idsecconf2023 - Satria Ady Pradana - Launch into the Stratus-phere Adversary ...
 
What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)
What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)
What's new with JavaScript in GNOME: The 2020 edition (GUADEC 2020)
 
BarcelonaJUG2016: walkmod: how to run and design code transformations
BarcelonaJUG2016: walkmod: how to run and design code transformationsBarcelonaJUG2016: walkmod: how to run and design code transformations
BarcelonaJUG2016: walkmod: how to run and design code transformations
 
C# 6.0 Preview
C# 6.0 PreviewC# 6.0 Preview
C# 6.0 Preview
 

Mais de Alessandro Molina

PyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdfPyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdfAlessandro Molina
 
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For AssetsEP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For AssetsAlessandro Molina
 
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...Alessandro Molina
 
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATESPyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATESAlessandro Molina
 
PyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitPyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitAlessandro Molina
 
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrongPyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrongAlessandro Molina
 
PyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development UpdatedPyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development UpdatedAlessandro Molina
 
Post-Mortem Debugging and Web Development
Post-Mortem Debugging and Web DevelopmentPost-Mortem Debugging and Web Development
Post-Mortem Debugging and Web DevelopmentAlessandro Molina
 
MongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profitMongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profitAlessandro Molina
 
PyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with MingPyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with MingAlessandro Molina
 
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...Alessandro Molina
 
EuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingEuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingAlessandro Molina
 
PyGrunn2013 High Performance Web Applications with TurboGears
PyGrunn2013  High Performance Web Applications with TurboGearsPyGrunn2013  High Performance Web Applications with TurboGears
PyGrunn2013 High Performance Web Applications with TurboGearsAlessandro Molina
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Alessandro Molina
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsAlessandro Molina
 

Mais de Alessandro Molina (15)

PyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdfPyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdf
 
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For AssetsEP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
 
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
 
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATESPyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
 
PyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitPyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profit
 
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrongPyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
 
PyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development UpdatedPyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development Updated
 
Post-Mortem Debugging and Web Development
Post-Mortem Debugging and Web DevelopmentPost-Mortem Debugging and Web Development
Post-Mortem Debugging and Web Development
 
MongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profitMongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profit
 
PyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with MingPyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with Ming
 
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
 
EuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingEuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears Training
 
PyGrunn2013 High Performance Web Applications with TurboGears
PyGrunn2013  High Performance Web Applications with TurboGearsPyGrunn2013  High Performance Web Applications with TurboGears
PyGrunn2013 High Performance Web Applications with TurboGears
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 

Último

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 

Último (20)

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 

From SQLAlchemy to Ming with TurboGears2

  • 1. From SQLAlchemy to Ming with TurboGears2 Alessandro Molina alessandro.molina@axant.it @__amol__
  • 2. Simple, Stupid, Serviceable ● We wanted to offer to development team members the opportunity to take a first look at MongoDB. ● We wanted to do this by letting them write an actual web app using Python. ● We wanted a real use case: “expenses and incomings” tracking (serviceable) ● We wanted everyone to understand how it is expected to work (stupid) ● Must be blazing fast to implement, we don't have a lot of time (simple)
  • 3. Involved Technologies ● Python → http://www.python.org ● TurboGears2 → http://www.turbogears.org ● SQLAlchemy → http://www.sqlalchemy.org ● Ming → http://merciless.sourceforge.net/index.html ● Genshi → http://genshi.edgewall.org ● ToscaWidgets → http://toscawidgets.org ● Sprox → http://www.sprox.org
  • 4. Python Technologies ● Why? Needed a WebApp ready in 5 minutes while being possible to quickly play with the code ● Python: Our team is manly python developers based ● TurboGears2: Our team is used to TG. Object Dispatch is really comfortable and the framework is incredibly fast to start with while still making possible to quickly get under the hood. ● Genshi: clean and plain xhtml, even designers can understand it, also it came by default ● ToscaWidgets: Can do most of the HTML for us ● Sprox: Can do most of the CRUD for us
  • 5. Quickstarting Our Project (tg2dev)Quasar-2:tuts amol$ paster quickstart mt_sqla ● Project Structure Enter package name [mt_sqla]: paster quickstart mt_sqla (tg2dev)Quasar-2:tuts amol$ Enter package name [mt_sqla]: Would you prefer mako templates? (yes/[no]): Do you need prefer mako templates? (yes/[no]): Would you authentication and authorization in this project? ([yes]/no): with Controllers Selected need implied templates: authorization in this project? ([yes]/no): Do you and authentication and Selected and implied templates: tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template for Index Page (tg2dev)Quasar-2:mt-sqla amol$ python setup.py develop (tg2dev)Quasar-2:mt-sqla amol$ python setup.py develop paster srunning develop paster srunning develop Installed /Users/amol/wrk/tuts/mt-sqla Installed /Users/amol/wrk/tuts/mt-sqla ● Models for Users, (tg2dev)Quasar-2:mt-sqla amol$ paster setup-app development.ini (tg2dev)Quasar-2:mt-sqla amol$ paster setup-app development.ini Running setup_config() from mt_sqla.websetup Running setup_config() from mt_sqla.websetup Creating tables Groups and Creating tables (tg2dev)Quasar-2:mt-sqla amol$ paster serve development.ini (tg2dev)Quasar-2:mt-sqla amol$ paster serve development.ini Starting server in PID 23939. Permission serving on server in PID 23939. Starting http://127.0.0.1:8080 serving on http://127.0.0.1:8080 ● Authentication (tg2dev)Quasar-2:tuts amol$ paster quickstart –ming mt_ming Enter package name [mt_ming]: paster quickstart –ming mt_ming (tg2dev)Quasar-2:tuts amol$ Enter package name [mt_ming]: and Authorization Would you prefer mako templates? (yes/[no]): Do you need prefer mako templates? (yes/[no]): Would you authentication and authorization in this project? ([yes]/no): Selected need implied templates: authorization in this project? ([yes]/no): Do you and authentication and Selected and implied templates: tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template tg.devtools#turbogears2 TurboGears 2. Standard Quickstart Template ● Both on SQLA (tg2dev)Quasar-2:mt-ming amol$ python setup.py develop (tg2dev)Quasar-2:mt-ming amol$ python setup.py develop paster srunning develop paster srunning develop Installed /Users/amol/wrk/tuts/mt-ming and Ming Installed /Users/amol/wrk/tuts/mt-ming (tg2dev)Quasar-2:mt-ming amol$ paster setup-app development.ini (tg2dev)Quasar-2:mt-ming amol$ paster setup-app development.ini Running setup_app() from mt_ming.websetup Running setup_app() from mt_ming.websetup (tg2dev)Quasar-2:mt-ming amol$ paster serve development.ini (tg2dev)Quasar-2:mt-ming amol$ paster serve development.ini Starting server in PID 23939. serving on server in PID 23939. Starting http://127.0.0.1:8080 serving on http://127.0.0.1:8080
  • 6. Overview Browser Genshi ToscaWidgets TurboGears Controller Code Sprox (TGAdmin) Ming SQLAlchemy
  • 7. SQLAlchemy ● Supports pratically everything: PostgresSQL, MySQL, SQLite, Firebird, Oracle, MSSQL, Sybase, DB2, Informix, SAPDB, MSAccess ● Declarative ORM layer with access to a powerful and flexible query builder ● Unlike many tools, it never enforces schemas or relies on naming conventions of any kind. ● Unit Of Work system organizes pending insert/update/delete operations into queues and flushes them all in one batch (Patterns of Enterprise Application Architecture - Martin Fowler)
  • 8. Python MongoDB Ecosystem ● PyMongo: Driver for MongoDB, everything is a dictionary ● MongoEngine: ORM, query language is familiar to Django users ● Ming: ORM, query language is familiar to SQLAlchemy users ● MongoKit: ORM, written to be as simple and light as possible MongoKit Ming class BlogPost(Document): class WikiComment(MappedClass): structure = { class __mongometa__: 'title':unicode, session = session 'body':unicode, name = 'wiki_comment' 'author':unicode, 'date_creation':datetime.datetime, _id = FieldProperty(schema.ObjectId) 'rank':int text=FieldProperty(str, if_missing='') } page_id = ForeignIdProperty('WikiPage') page=RelationProperty('WikiPage') tutorial.BlogPost.find({'body': {'$exists': True}}) WikiComment.query.find({'text':{'$exists':True}}) MongoEngine PyMongo class User(Document): post = {"author": "Mike", email = StringField(required=True) ... "text": "My first blog post!", first_name = StringField(max_length=50) ... "tags": ["mongodb", "python"], last_name = StringField(max_length=50) ... "date": datetime.datetime.utcnow()} Users.objects(age__lte=18) db.posts.find({"author": "Mike"})
  • 9. Ming ● SQLAlchemy inspired, easy to catch up if you are used to SQLAlchemy ● Declarative ORM layer, use ORM through objects and get direct access to mongo through collections ● Integrated Migrations (deprecated attributes and even on-demand lazy migration code) ● Unit of Work, we tried it, we loved it, we wanted it even on MongoDB ● Mongo In Memory, complete implementation of MongoDB in memory for unit testing
  • 10. Some Little Magic (TGAdmin) ● It did CRUD for us. ● Works both with SQLAlchemy and Ming ● Comes for free with TurboGears2 ● Sprox based, deeply customizable
  • 11. Storing our Data from sqlalchemy import Table, Column from ming import schema as s from sqlalchemy import Table, Column from sqlalchemy.types import Unicode, Integer, from ming import schema as s from ming.orm import FieldProperty, Mapper Float, sqlalchemy.types import Unicode, Integer, from DateTime from ming.orm import FieldProperty, Mapper from ming.orm.declarative import MappedClass Float, DateTime from datetime import datetime from ming.orm.declarative import MappedClass from session import DBSession from datetime import datetime from session import DBSession from datetime import datetime from datetime import datetime class MoneyTransfer(DeclarativeBase): class MoneyTransfer(MappedClass): class MoneyTransfer(DeclarativeBase): __tablename__ = 'money_transfers' class MoneyTransfer(MappedClass): class __mongometa__: __tablename__ = 'money_transfers' class __mongometa__: session = DBSession session = DBSession name = 'money_transfers' name = 'money_transfers' uid = Column(Integer, autoincrement=True, _id = FieldProperty(s.ObjectId) uid = Column(Integer,primary_key=True) autoincrement=True, _id = FieldProperty(s.ObjectId) date = FieldProperty(s.DateTime, primary_key=True) date = Column(DateTime, default=datetime.now) date = FieldProperty(s.DateTime, if_missing=datetime.now) sign = =Column(Integer, default=1) date Column(DateTime, default=datetime.now) if_missing=datetime.now) sign = FieldProperty(s.Int, if_missing=1) sign = Column(Integer, default=1) description = Column(Unicode(255)) sign = FieldProperty(s.Int, if_missing=1) description = FieldProperty(s.String) description = Column(Unicode(255)) value = Column(Float, default=0) description = FieldProperty(s.String) value = FieldProperty(s.Float, if_missing=0) value = Column(Float, default=0) value = FieldProperty(s.Float, if_missing=0)
  • 12. Retrieving and Displaying Data from tw.forms import DataGrid from tw.forms import DataGrid from tw.forms.datagrid DataGrid from tw.forms import import Column from tw.forms.datagrid DataGrid from tw.forms import import Column from tw.forms.datagrid import Column from tw.forms.datagrid import Column transactions_grid = DataGrid(fields=[ transactions_grid = DataGrid(fields=[ transactions_grid 'date'), Column('Date', = DataGrid(fields=[ transactions_grid 'date'), Column('Date', = DataGrid(fields=[ Column('Date', 'date'), Column('Description', 'description'), Column('Date', 'date'), Column('Description', 'description'), Column('Description', 'description'), Column('Value', lambda row:row.value*row.sign)]) Column('Description', 'description'), Column('Value', lambda row:row.value*row.sign)]) Column('Value', lambda row:row.value*row.sign)]) Column('Value', lambda row:row.value*row.sign)]) class RootController(BaseController): class RootController(BaseController): class RootController(BaseController): @expose('mt_sqla.templates.index') class RootController(BaseController): @expose('mt_ming.templates.index') @expose('mt_sqla.templates.index') def index(self): @expose('mt_ming.templates.index') def index(self): def index(self): DBSession.query(MoneyTransfer).all() transactions = def index(self): MoneyTransfer.query.find().all() transactions = transactions = DBSession.query(MoneyTransfer).all() total = sum((t.value*t.sign for t in transactions)) transactions = MoneyTransfer.query.find().all() total = sum((t.value*t.sign for t in transactions)) total = sum((t.value*t.sign for t in transactions)) return dict(page='index', total = sum((t.value*t.sign for t in transactions)) return dict(page='index', return dict(page='index', transactions=transactions, return dict(page='index', transactions=transactions, transactions=transactions, transactions_grid=transactions_grid, transactions=transactions, transactions_grid=transactions_grid, transactions_grid=transactions_grid, total=total) transactions_grid=transactions_grid, total=total) total=total) total=total) <div style="width:650px; margin-top:20px;"> <div style="width:650px; margin-top:20px;"> <a href="${tg.url('/admin/moneytransfers/new')}">Add New Transaction</a> <a href="${tg.url('/admin/moneytransfers/new')}">Add New Transaction</a> ${transactions_grid(transactions)} ${transactions_grid(transactions)} <div style="text-align:right;"><strong>AVAILABLE:</strong> ${total}</div> <div style="text-align:right;"><strong>AVAILABLE:</strong> ${total}</div> </div> </div>
  • 13. What changed ● Template remained the same. Thanks god we have an ORM. ● Had to change the model. ● Had to change just 1 line of controller code to retrieve the data. Ming and SQLA are similar enough ● Did we really need to change that line? We just want to get a list of objects...
  • 14. Sprox, abstraction over abstraction ● ORMProvider, provides an abstraction over the ORM ● ORMProviderSelector, automatically detects the provider to use from a model. ● Mix those together and you have a db independent layer. ● Provider.query(self, entity, limit=None, offset=0, limit_fields=None, order_by=None, desc=False) → get all objects of a collection ● Provider.get_obj(self, entity, params) → get an object ● Provider.update(self, entity, params) → update an object ● Provider.create(self, entity, params) → create a new object SQLAlchemy transactions = DBSession.query(MoneyTransfer).all() transactions = DBSession.query(MoneyTransfer).all() Sprox count, transactions = provider.query(MoneyTransfer) Ming count, transactions = provider.query(MoneyTransfer) transactions = MoneyTransfer.query.find().all() transactions = MoneyTransfer.query.find().all()
  • 15. Experiments Experience ● Starting with a really simple use case made people get comfortable with MongoDB and feel confident enough to start learning more complex features. ● The idea of being possible to use sprox to abstract over the db, making possible to switch back anytime, created a “safety net” idea in people. ● When people feel safe they start experimenting a lot more and learn by themselves.