Il model prende vita

All'avvio del processo che istanzia la applicazione Genropy viene letto il file instanceconfig.xml dell'istanza e in particolare i packages da includere.

Per ogni package incluso e per ogni sua tabella viene invocato il metodo config_db, il cui scopo è quello di costruire un'unica Bag (Struttura) che contiene tutte le informazioni delle tabelle dell'applicazione.

Per come è costruita la Bag, ogni package ha modo di intervenire sulla parte già costruita e in questo modo un package può andare a customizzare il funzionamento di un package che lo preceda nella configurazione.

La struttura segue sempre questa gerarchia

  • Database
    • packages
      • package p1
        • tables
          • table t1
            • columns
              • column c1 column c2 ... column cn
          • table t2
          • ...
          • table tn
      • package p2
      • ...
      • package pn
In [1]:
from gnr.app.gnrapp import GnrApp

#istanzio oggetto GnrApp passando il nome dell'istanza di sandbox chiamata sandboxpg
app = GnrApp('sandboxpg')

#dell'oggetto GnrApp mi interessa al momento solo il puntatore all'oggetto GnrSqlDb  
#questo è il mapper corrispondente dal database dell'applicazione

mydb = app.db

#dell'oggetto mydb adesso vediamo solo il model

mymodel = mydb.model

# in src abbiamo la Bag che corrisponde alla struttura dell'intero database
model_structure = mymodel.src

# navighiamo la struttura con il path fino a vedere le tabelle del package glbl
# E facciamoci tornare le keys della bag a quel livello
model_structure['packages'].keys()
Out[1]:
['sys', 'adm', 'glbl', 'sandbox', 'tutor', 'test15', 'biz', 'fatt']
In [2]:
model_structure['packages.glbl'].keys()
Out[2]:
['tables']
In [3]:
model_structure['packages.glbl.tables'].keys()
Out[3]:
['comune', 'localita', 'nazione', 'nuts', 'provincia', 'regione']
In [4]:
model_structure['packages.glbl.tables.provincia'].keys()
Out[4]:
['columns', 'virtual_columns']
In [5]:
model_structure['packages.glbl.tables.provincia.columns'].keys()
Out[5]:
['sigla',
 'regione',
 'nome',
 'nome_locale',
 'codice',
 'codice_istat',
 'ordine',
 'ordine_tot',
 'cap_valido',
 'nuts',
 'mill_si',
 'mill_no',
 'mill_ast']

Una volta che la Bag struttura è stata costruita viene subito dopo avviata una fase build in cui per ogni elemento della struttura viene istanziato l'equivalente oggetto Python. Il risultato è un albero di oggetti in memoria parallelo e del tutto equivalente alla Bag della struttura appena vista.

In [6]:
#l'albero degli oggetti viene messo nella proprietà obj del model
#anche questo può essere attraversato in profondità
#ma diversamente dalla Bag struttura che permetteva di farlo con un unico path qui bisogna usare 
#gli appositi metodi children

my_objects_tree = mymodel.obj
my_objects_tree.children['glbl'].tables.children['provincia'].children['columns'].keys()
Out[6]:
['sigla',
 'regione',
 'nome',
 'nome_locale',
 'codice',
 'codice_istat',
 'ordine',
 'ordine_tot',
 'cap_valido',
 'nuts',
 'mill_si',
 'mill_no',
 'mill_ast']

L'oggetto SqlTable

Nella pratica comune della programmazione con Genropy avremo a che fare principalmente con l'oggetto SqlTable che è il mapper di una table del database.

Una volta che abbiamo a disposizione l'handle del database, per poter operare sull'oggetto SqlTable usiamo il metodo table

In [7]:
clienti_tbl = mydb.table('fatt.cliente')
clienti_tbl.name_plural
Out[7]:
'!![it]Clienti'

L'oggetto SqlTable possiede tutte le proprietà della table, che abbiamo specificato nel modulo di model e tutti i metodi che abbiamo definito.

In [8]:
clienti_tbl.pkey
Out[8]:
'id'
In [9]:
clienti_tbl.columns.keys()
Out[9]:
['id',
 '__ins_ts',
 '__del_ts',
 '__mod_ts',
 '__ins_user',
 'ragione_sociale',
 'indirizzo',
 'provincia',
 'comune_id',
 'cliente_tipo_codice',
 'pagamento_tipo_codice',
 'note',
 'email',
 'data_iscrizione_newsletter',
 'data_disiscrizione_newsletter']

Ma soprattutto l'oggetto SqlTable è il punto di partenza ideale per eseguire una serie di operazioni sul database, sia in lettura che in scrittura.