Browse Source

accesso a più db + cursori multipli in environ

db_access
Andrea Papotti 13 years ago
parent
commit
4af1158732
4 changed files with 123 additions and 21 deletions
  1. +2
    -2
      controllers/demo/due.py
  2. +50
    -0
      controllers/demo/sql.py
  3. +62
    -17
      decorators.py
  4. +9
    -2
      dispatch_wsgi.py

+ 2
- 2
controllers/demo/due.py View File

@@ -3,12 +3,12 @@


from decorators import WSGITemplate # decoratore ( singleton ) from decorators import WSGITemplate # decoratore ( singleton )


wsgit = WSGITemplate()
wsgitmpl = WSGITemplate()


# #
# esempio minimo di controller WSGI # esempio minimo di controller WSGI
# #
@wsgit.template( 'template1.tmpl' )
@wsgitmpl.template( 'template1.tmpl' )
def application( environ, start_response ): def application( environ, start_response ):
from pprint import pformat from pprint import pformat




+ 50
- 0
controllers/demo/sql.py View File

@@ -0,0 +1,50 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

from decorators import WSGIMySQL # decoratore ( singleton )

wsgisql = WSGIMySQL()

#
# esempio minimo di controller WSGI
#
@wsgisql.db( 'mywiki', 'shoot' )
def application( environ, start_response ):

cur = environ['mysql.mywiki.cur']

#
# esecuzione query
#
cur.execute( 'SHOW tables;' )

#
# recupero record e generazione html
#

start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )

yield "<h1>elenco tabelle presenti nel db mywiki</h1>"

for record in cur.fetchall():
yield str( record ) + "<br>"

#
# recupero secondo cursore
#

cur2 = environ['mysql.shoot.cur']

#
# esecuzione query
#
cur2.execute( 'SHOW tables;' )

#
# recupero record e generazione html
#

yield "<h1>elenco tabelle presenti nel db shoot</h1>"

for record in cur2.fetchall():
yield str( record ) + "<br>"

+ 62
- 17
decorators.py View File

@@ -36,41 +36,82 @@ class WSGIMySQL( object ):
__metaclass__ = Singleton __metaclass__ = Singleton


def __init__( self, dsn, *args ): def __init__( self, dsn, *args ):
""" inizializza le connessioni a 1 o più database.
In caso di connessioni a databese multipli,
le connessioni sono identificate tramite ALIAS
o in mancanza di questo tramite DB

ogni singolo dsn deve essere un dizionario con le chiavi:
- DB : nome del database
- HOST : host a cui connettersi
- USER : username da utilizzare per connettersi
- PASSWORD : password da utilizzare per connettersi
- ALIAS : (opzionale) identificativo della connessione
"""
import MySQLdb import MySQLdb


self.__dsn = dsn
self.__pool = [ self.__newconn() ]
#
# aggiungiamo il primo dsn in cima alla lista
#
args = list( args )
args.insert( 0, dsn )

#
# creiamo il nostro dizionario di dizionari
#
self.__dsn = { dsndict.get( 'ALIAS', dsndict['DB'] ):dsndict for dsndict in args }

#
# verifichiamo che non ci siano alias duplicati
#
if len( self.__dsn.keys() ) != len( args ):
raise Exception( "WSGIMySQL :: conflicting alias in dsn list" )

#
# tentiamo di creare la prima connessione verso TUTTI i dsn passati
#

for alias, dsndict in self.__dsn.iteritems():
dsndict['pool'] = [ self.__newconn( alias ) ]

self.__dict_cursor = MySQLdb.cursors.DictCursor self.__dict_cursor = MySQLdb.cursors.DictCursor




def __newconn( self ):
def __newconn( self, alias ):
import MySQLdb import MySQLdb


return MySQLdb.connect( return MySQLdb.connect(
host = self.__dsn["HOST"],
user = self.__dsn["USER"],
passwd = self.__dsn["PASSWORD"],
db = self.__dsn["DB"]
host = self.__dsn[ alias ]["HOST"],
user = self.__dsn[ alias ]["USER"],
passwd = self.__dsn[ alias ]["PASSWORD"],
db = self.__dsn[ alias ]["DB"]
) )


def db( self, *args ): def db( self, *args ):
def real_decorator( wsgi_application ): def real_decorator( wsgi_application ):
def wrapper( environ, start_response ): def wrapper( environ, start_response ):
try:
conn = self.__pool.pop( 0 )
except IndexError:
conn = self.__newconn()
connections = []

for arg in args:
try:
conn = self.__dsn[ arg ]['pool'].pop( 0 )
except IndexError:
conn = self.__newconn( arg )

connections.append( conn )


cur = conn.cursor( self.__dict_cursor )
cur = conn.cursor( self.__dict_cursor )


environ['mysql.cur'] = cur
environ['mysql.' + arg + '.cur'] = cur


try: try:
for item in wsgi_application( environ, start_response ): for item in wsgi_application( environ, start_response ):
yield item yield item
finally: finally:
conn.commit()
self.__pool.append( conn )
for arg in args:
conn = connections.pop(0)
conn.commit()
self.__dsn[ arg ]['pool'].append( conn )


return wrapper return wrapper


@@ -78,5 +119,9 @@ class WSGIMySQL( object ):




def __del__( self ): def __del__( self ):
for conn in self.__pool:
conn.close()
#
# chiudiamo tutte le connessioni attualmente aperte
#
for dsndict in self.__dsn.items():
for conn in dsndict['pool']:
conn.close()

+ 9
- 2
dispatch_wsgi.py View File

@@ -21,12 +21,19 @@ WSGITemplate( basedir='views' )
# #
from decorators import WSGIMySQL from decorators import WSGIMySQL
WSGIMySQL( WSGIMySQL(
dsn = dict(
dict(
DB = "mywiki", DB = "mywiki",
HOST = "localhost", HOST = "localhost",
USER = "corso", USER = "corso",
PASSWORD = "pwdcorso" PASSWORD = "pwdcorso"
)
),
dict(
DB = "shootout",
HOST = "localhost",
USER = "root",
PASSWORD = "server",
ALIAS = "shoot"
),
) )






Loading…
Cancel
Save