SQLObject makes accessing your database seem very much like using any other Python objects. Behind the scenes, SQL queries are being run as you do things. To insert a new row into your database, just instantiate an object from the appropriate class. Here's an example with debug logging (?debug=1&debugOutput=1) turned on:
>>> Book(isbn="1234567890", title="A Fistful of Yen", description="An evocative look at Japanese currency surrounded by hands.")
1/QueryIns: INSERT INTO book (isbn, description, title) VALUES ('1234567890', 'An evocative look at Japanese currency surrounded by hands.', 'A Fistful of Yen')
1/QueryIns-> 1
1/COMMIT : auto
1/QueryOne: SELECT isbn, title, description FROM book WHERE id = 1
1/QueryR : SELECT isbn, title, description FROM book WHERE id = 1
;
1/QueryOne-> (u'1234567890', u'A Fistful of Yen', 'An evocative look at Japanese currency surrounded by hands.')
1/COMMIT : auto
]]>
Though there are ways to have keys handled differently, SQLObject works best in its default setup where each table has an integer primary key. You can get at any SQLObject's primary key through the "id" attribute. SQLObject makes it really easy to retrieve by ID.
>>> Book.get(1)
]]>
When you specify that a column is an "alternateID", as we did for the "isbn", SQLObject automatically creates a classmethod so that you can use to search on those values:
>>> Book.byIsbn("1234567890")
1/QueryOne: SELECT id, isbn, title, description FROM book WHERE isbn = '1234567890'
1/QueryR : SELECT id, isbn, title, description FROM book WHERE isbn = '1234567890'
1/QueryOne-> (1, u'1234567890', u'A Fistful of Yen', 'An evocative look at Japanese currency surrounded by hands.')
1/COMMIT : auto
]]>
Of course, there are plenty of times when we need to do searches beyond just simple ID lookups. SQLObject provides a "select" classmethod that lets you specify many queries in more Python-like terms. Your class has a special "q" attribute that gives you access to a placeholder for a real attribute to use in queries. For example, to query on the isbn column, you would use Book.q.isbn. Here's a sample query:
>>> list(Book.select(AND(LIKE(Book.q.title, "%Fistful%"), Book.q.isbn=="1234567890")))
1/Select : SELECT book.id, book.isbn, book.title, book.description FROM book WHERE ((book.title LIKE '%Fistful%') AND (book.isbn = '1234567890'))
1/QueryR : SELECT book.id, book.isbn, book.title, book.description FROM book WHERE ((book.title LIKE '%Fistful%') AND (book.isbn = '1234567890'))
1/COMMIT : auto
]
]]>
In the example above, you'll note the call to "list" around the Book.select call. The select classmethod returns a SelectResults object. The neat thing about SelectResults is that until you start pulling data out of it, it's just a placeholder for the results. Rather than converting the results to a list, we could have added .count() to the end of the select call in order to just retrieve the number of matching rows.
Updates are very easy: just change the attribute! Every time you change an attribute, SQLObject will run an UPDATE SQL statement. Sometimes, though, you may need to change several columns at once and don't want to run individual updates for each. Your instances have a "set" method that lets you set them all at once. Here are examples of both styles:
>>> book.title = "A Fistful of Foobar"
1/Query : UPDATE book SET title = 'A Fistful of Foobar' WHERE id = 1
1/QueryR : UPDATE book SET title = 'A Fistful of Foobar' WHERE id = 1
1/COMMIT : auto
>>> book.set(title="A Fistful of Yen 2: Electric Boogaloo", isbn="37")
1/Query : UPDATE book SET isbn = '37', title = 'A Fistful of Yen 2: Electric Boogaloo' WHERE id = 1
1/QueryR : UPDATE book SET isbn = '37', title = 'A Fistful of Yen 2: Electric Boogaloo' WHERE id = 1
1/COMMIT : auto
TurboGears makes it easy to use transactions, via its "connection hub". The connection hub automatically connects to the database as needed, and also gives you methods to begin, commit, rollback or end transactions. Here's an example of transactions at work:
>>> book.title
'A Fistful of Yen 2: Electric Boogaloo'
>>> hub.begin()
>>> book.title = "A Fistful of Yen 3: The Sequel That Shouldn't Be"
1/Query : UPDATE book SET title = 'A Fistful of Yen 3: The Sequel That Shouldn''t Be' WHERE id = 1
1/QueryR : UPDATE book SET title = 'A Fistful of Yen 3: The Sequel That Shouldn''t Be' WHERE id = 1
>>> hub.rollback()
1/ROLLBACK:
>>> hub.end()
>>> book.title
"A Fistful of Yen 3: The Sequel That Shouldn't Be"
>>> book.sync()
1/QueryOne: SELECT isbn, title, description FROM book WHERE id = 1
1/QueryR : SELECT isbn, title, description FROM book WHERE id = 1
1/QueryOne-> (u'37', u'A Fistful of Yen 2: Electric Boogaloo', 'An evocative look at Japanese currency surrounded by hands.')
1/COMMIT : auto
>>> book.title
'A Fistful of Yen 2: Electric Boogaloo'
Notice that, unlike in the previous examples, there was no COMMIT : auto for these queries. That's because we turned on transactions, so autocommit was automatically turned off. You can also specify that you don't want autocommit by adding an autoCommit=0 parameter to your connection URI.
It is also worth noting that the book object that we had in memory did not revert to its database state automatically on rollback. By calling sync(), the values are reloaded from the database.
Once you've had enough of "A Fistful of Yen 2", you can delete it from the database by using the destroySelf method.