gestion des filtres, des comXre, quelques optimisations
authorThomas NOEL <thomas@new-dev.(none)>
Fri, 4 Jul 2008 01:46:16 +0000 (21:46 -0400)
committerThomas NOEL <thomas.noel@auf.org>
Fri, 4 Jul 2008 01:46:16 +0000 (21:46 -0400)
rest.wsgi

index e925d0c..eeef891 100644 (file)
--- a/rest.wsgi
+++ b/rest.wsgi
@@ -20,6 +20,8 @@ from pymssql import connect
 from jinja import Environment, FileSystemLoader
 from jinja.filters import stringfilter
 import jinja.exceptions
+# on prepare un environnement jinja toujours disponible
+ejinja = Environment(loader=FileSystemLoader('/home/thomas/public_html/'))
 
 # TODO systeme de cache : beaker
 # from beaker.middleware import CacheMiddleware
@@ -37,47 +39,75 @@ mapper.resource('comdep','comdep')
 mapper.resource('dempub','dempub')
 mapper.resource('compub','compub')
 mapper.resource('comare','comare')
-# pour les comarexxx où xxx est un code d'implantation
-mapper.resource('comarei','comare:(impl)',controller='comare')
-mapper.resource('comsra','comsre')
-mapper.resource('comsrai','comsre:(impl)',controller='comsre')
+mapper.resource('comarei','comare:(impl)',controller='comare') # pour les comarexxx où xxx est un code d'implantation
+mapper.resource('comsre','comsre')
+mapper.resource('comsrei','comsre:(impl)',controller='comsre')
+mapper.resource('comxre','comxre') # comxre = comare + comsre
+mapper.resource('comxrei','comxre:(impl)',controller='comxre')
 mapper.resource('dem','dem')
 mapper.resource('com','com')
 
+
 class objetsql(object):
     """objet de base : dispose d'un accès à MS-SQL (lire les données) et d'un accès à jinja (rendu des données)"""
     def __init__(self, environ):
        self.environ = environ
+        parse_formvars(environ)                                            # extraction des variables de query_string et POST
+       self.filters = environ['paste.parsed_formvars'][0].dict_of_lists() # puis traduction en dictionnaire {var1:[val1,val2], ...}
     def template(self,template):
-       self.jinja = Environment(loader=FileSystemLoader('/home/thomas/public_html/'))
         self.outputformat = self.environ['wsgiorg.routing_args'][1].get('format','xml')
-       return self.jinja.get_template('%s.%s' % (template,self.outputformat))
+       return ejinja.get_template('%s.%s' % (template,self.outputformat))
     def cursor(self):
-        if not hasattr(self,'bd'):
-            self.bd = connect(host=rest_config.host,user=rest_config.user,password=rest_config.password,database=rest_config.database)
-       return self.bd.cursor()
+        if not hasattr(self,'db_connect'):
+            self.db_connect = connect(host=rest_config.host,user=rest_config.user,password=rest_config.password,database=rest_config.database)
+       if not hasattr(self,'db_cursor'):
+           self.db_cursor = self.db_connect.cursor()
+       return self.db_cursor
+    def __del__(self):
+        # coupe la connexion à MSSQL à la mort de l'objet (normalement ça se fait tout seul mais j'en suis pas sûr sûr)
+        if hasattr(self,'db_connect'):
+           db_connect.close()
 
 class document(objetsql):
     """objet document CODA (demlog, comlog, demdep... ils ont tous le même format)"""
-    def __init__(self, environ, code_document='%', basename_template='document'):
+    accept_like_filters = [ 'code', 'demandeur', 'approbateur', 'code_service', 'statut', 'fournisseur' ]
+    def __init__(self, environ, code_document='%', prefix_template='document'):
         super(document, self).__init__(environ)
         self.code_document = code_document
-        self.basename_template = basename_template
+        self.prefix_template = prefix_template
+       # filtrage : on extrait la liste des filtres "acceptes" pour en faire des where
+        sqlwhere = []
+       for filter in self.accept_like_filters:
+            if filter in self.filters:
+               or_list = []
+               for v in self.filters[filter]:
+                   or_list.append("%s like '%s'" % (filter,v))
+               sqlwhere.append('(' + ' or '.join(or_list) + ')')
+       # TODO : ajouter filtres min_*/max_*, avant/apres dans ce sqlwhere
+       self.sqlwhere = ''
+       for f in sqlwhere:
+           self.sqlwhere += ' and ' + f
+       # filtrage : valeur en cas de limite ("top n" en ODBC), 50 maxi
+       if 'limite' in self.filters:
+           self.sqllimit = min( int(self.filters['limite'][0]), 50 )
+       else:
+           self.sqllimit = 15
+       # TODO : ajouter filtres tri_asc/tri_desc
 
     def _get_index(self, code):
         """renvoie une liste de documents"""
        # connexion a la base de données
        cursor = self.cursor()
        # extraction des données
-       cursor.execute("select top 15 * from auf_v_acces_demcom where code like '%s' order by date_modif desc" % code)
-       index = {}
-       index['code'] = code
+       cursor.execute("select top %d * from auf_v_acces_demcom where (code like '%s') %s order by date_modif desc" % ( self.sqllimit, code, self.sqlwhere ) )
        items = []
        while 1:
            item = dict_fetchone( cursor )
            if item == None: break
            item['code_rest'] = coda2rest(item['code'])
            items.append(item)
+       index = {}
+       index['code'] = code
        index['documents'] = items
        return index
 
@@ -85,7 +115,7 @@ class document(objetsql):
         """renvoie la liste des détails pour un document"""
         details = []
        cursor = self.cursor()
-        cursor.execute("select * from auf_v_acces_dtls_demcom where code like '%s' and numero = %d" % (code, id))
+        cursor.execute("select * from auf_v_acces_dtls_demcom where (code like '%s') and (numero = %d)" % (code, id))
         while 1:
             detail = dict_fetchone(cursor)
             if detail == None: break
@@ -95,7 +125,7 @@ class document(objetsql):
     def _get_document(self,code,id):
         """renvoie un document"""
        cursor = self.cursor()
-        cursor.execute("select top 1 * from auf_v_acces_demcom where code like '%s' and numero = %d" % (code, id))
+        cursor.execute("select top 1 * from auf_v_acces_demcom where (code like '%s') and (numero = %d) %s" % (code, id, self.sqlwhere))
         document = dict_fetchone(cursor)
        if document == None:
            raise "document inexistant"
@@ -105,16 +135,16 @@ class document(objetsql):
 
     def index(self):
         """renvoie une liste de documents formatée"""
-        template = self.template('%s-index' % self.basename_template) # préparation du modèle
-       index = self._get_index( self.code_document )                 # extraction des documents concernés
-       output = template.render( index )                             # formattage via le modèle
+        template = self.template('%s-index' % self.prefix_template) # préparation du modèle
+       index = self._get_index( self.code_document )               # extraction des documents concernés
+       output = template.render( index )                           # formattage via le modèle
        return self.outputformat, output
 
     def show(self):
         """renvoie un document formaté"""
         # return 'txt', '%s' % self.environ # pour debug
         id = int(self.environ['wsgiorg.routing_args'][1]['id'])
-        template = self.template( self.basename_template )
+        template = self.template( self.prefix_template )
         document = self._get_document( self.code_document, id )
         output = template.render( document )
        return self.outputformat, output
@@ -153,7 +183,7 @@ class compub(document):
 
 class comsre(document):
     def __init__(self, environ):
-        # est-ce un appel de comsre ou comsrexxx (avec xxx = implantation)
+        # on distingue comsre et comsrexxx (avec xxx = implantation)
         impl = environ['wsgiorg.routing_args'][1].get('impl','%')
         super(comsre, self).__init__(environ, code_document = 'COM-SRE-%s' % impl)
 
@@ -162,13 +192,17 @@ class comare(document):
         impl = environ['wsgiorg.routing_args'][1].get('impl','%')
         super(comare, self).__init__(environ, code_document = 'COM-ARE-%s' % impl)
 
+class comxre(document):
+    def __init__(self, environ):
+        impl = environ['wsgiorg.routing_args'][1].get('impl','%')
+        super(comxre, self).__init__(environ, code_document = 'COM-%%RE-%s' % impl)
+
 #
 # fin des objets accessibles
 #
 
 def dispatcher(environ, start_response):
     """dispatch vers la bonne methode du bon objet, et retour WSGI"""
-    parse_formvars(environ)
     results = environ['wsgiorg.routing_args'][1]
     try:
         target_class = globals()[results['controller']]
@@ -191,7 +225,6 @@ def dispatcher(environ, start_response):
 application = RoutesMiddleware( dispatcher, mapper)
 # TODO : ajouter un middleware de cache (beaker, basé sur REQUEST_URI quand la methode est GET)
 
-
 #
 # petits utilitaires
 #