Momoko offers a few ways to interact with the database. The first one is the blocking client. This is just a small wrapper around Psycopg2. The other two are asynchronous clients. The example code can be found on Github. Only relevant code is shown on this page.
The blocking client:
class BaseHandler(tornado.web.RequestHandler):
@property
def db(self):
# Create a database connection when a request handler is called
# and store the connection in the application object.
if not hasattr(self.application, 'db'):
self.application.db = momoko.BlockingClient({
'host': 'localhost',
'database': 'momoko',
'user': 'frank',
'password': '',
'min_conn': 1,
'max_conn': 20,
'cleanup_timeout': 10
})
return self.application.db
class SingleQueryHandler(BaseHandler):
def get(self):
# Besides using a with statement everyting is the same as the normal
# Psycopg2 module
with self.db.connection as conn:
cursor = conn.cursor()
cursor.execute('SELECT 42, 12, 40, 11;')
self.write('Query results: %s' % cursor.fetchall())
self.finish()
The asynchronous client that uses callbacks:
class BaseHandler(tornado.web.RequestHandler):
@property
def db(self):
# Create a database connection when a request handler is called
# and store the connection in the application object.
if not hasattr(self.application, 'db'):
self.application.db = momoko.AsyncClient({
'host': 'localhost',
'database': 'momoko',
'user': 'frank',
'password': '',
'min_conn': 1,
'max_conn': 20,
'cleanup_timeout': 10
})
return self.application.db
class SingleQueryHandler(BaseHandler):
@tornado.web.asynchronous
def get(self):
# One simple query
self.db.execute('SELECT 42, 12, 40, 11;', callback=self._on_response)
def _on_response(self, cursor):
self.write('Query results: %s' % cursor.fetchall())
self.finish()
class BatchQueryHandler(BaseHandler):
@tornado.web.asynchronous
def get(self):
# These queries are executed all at once and therefore they need to be
# stored in an dictionary so you know where the resulting cursors
# come from, because they won't arrive in the same order.
self.db.batch({
'query1': ['SELECT 42, 12, %s, %s;', (23, 56)],
'query2': 'SELECT 1, 2, 3, 4, 5;',
'query3': 'SELECT 465767, 4567, 3454;'
}, self._on_response)
def _on_response(self, cursors):
for key, cursor in cursors.items():
self.write('Query results: %s = %s<br>' % (key, cursor.fetchall()))
self.finish()
class QueryChainHandler(BaseHandler):
@tornado.web.asynchronous
def get(self):
# Execute a list of queries in the order you specified
self.db.chain((
['SELECT 42, 12, %s, 11;', (23,)],
'SELECT 1, 2, 3, 4, 5;'
), self._on_response)
def _on_response(self, cursors):
for cursor in cursors:
self.write('Query results: %s<br>' % cursor.fetchall())
self.finish()
And the asynchronous callback-based client using Tornado’s gen module:
from tornado import gen
class BaseHandler(tornado.web.RequestHandler):
@property
def db(self):
# Create a database connection when a request handler is called
# and store the connection in the application object.
if not hasattr(self.application, 'db'):
self.application.db = momoko.AsyncClient({
'host': 'localhost',
'database': 'momoko',
'user': 'frank',
'password': '',
'min_conn': 1,
'max_conn': 20,
'cleanup_timeout': 10
})
return self.application.db
class SingleQueryHandler(BaseHandler):
@tornado.web.asynchronous
@gen.engine
def get(self):
# One simple query
cursor = yield gen.Task(self.db.execute, 'SELECT 42, 12, %s, 11;', (25,))
self.write('Query results: %s' % cursor.fetchall())
self.finish()
class BatchQueryHandler(BaseHandler):
@tornado.web.asynchronous
@gen.engine
def get(self):
# These queries are executed all at once and therefore they need to be
# stored in an dictionary so you know where the resulting cursors
# come from, because they won't arrive in the same order.
cursors = yield gen.Task(self.db.batch, {
'query1': ['SELECT 42, 12, %s, %s;', (23, 56)],
'query2': 'SELECT 1, 2, 3, 4, 5;',
'query3': 'SELECT 465767, 4567, 3454;'
})
for key, cursor in cursors.items():
self.write('Query results: %s = %s<br>' % (key, cursor.fetchall()))
self.finish()
class QueryChainHandler(BaseHandler):
@tornado.web.asynchronous
@gen.engine
def get(self):
# Execute a list of queries in the order you specified
cursors = yield gen.Task(self.db.chain, (
['SELECT 42, 12, %s, 11;', (23,)],
'SELECT 1, 2, 3, 4, 5;'
))
for cursor in cursors:
self.write('Query results: %s<br>' % cursor.fetchall())
self.finish()
class MultiQueryHandler(BaseHandler):
@tornado.web.asynchronous
@gen.engine
def get(self):
cursor1, cursor2, cursor3 = yield [
gen.Task(self.db.execute, 'SELECT 42, 12, %s, 11;', (25,)),
gen.Task(self.db.execute, 'SELECT 42, 12, %s, %s;', (23, 56)),
gen.Task(self.db.execute, 'SELECT 465767, 4567, 3454;')
]
self.write('Query 1 results: %s<br>' % cursor1.fetchall())
self.write('Query 2 results: %s<br>' % cursor2.fetchall())
self.write('Query 3 results: %s' % cursor3.fetchall())
self.finish()
class CallbackWaitHandler(BaseHandler):
@tornado.web.asynchronous
@gen.engine
def get(self):
self.db.execute('SELECT 42, 12, %s, 11;', (25,),
callback=(yield gen.Callback('q1')))
self.db.execute('SELECT 42, 12, %s, %s;', (23, 56),
callback=(yield gen.Callback('q2')))
self.db.execute('SELECT 465767, 4567, 3454;',
callback=(yield gen.Callback('q3')))
cursor1 = yield gen.Wait('q1')
cursor2 = yield gen.Wait('q2')
cursor3 = yield gen.Wait('q3')
self.write('Query 1 results: %s<br>' % cursor1.fetchall())
self.write('Query 2 results: %s<br>' % cursor2.fetchall())
self.write('Query 3 results: %s' % cursor3.fetchall())
self.finish()