Upload
pycon-italia
View
980
Download
3
Embed Size (px)
DESCRIPTION
Roberto Lupi
Citation preview
Un progetto in
GenroPyFramework tutto italiano
per applicazioni web e AJAX
sabato 29 maggio 2010
Un progetto in
GenroPyFramework tutto italiano
per applicazioni web e AJAX
gestionali
sabato 29 maggio 2010
Roberto Lupi@robertolupi
• 10 anni di esperienza web
• enterprise e intranet
• Clienti: Amadori, Merloni, 21 banche
• Italia e India
• oggi: direttore tecnico di MedMediasoftware per la sanità
• http://www.medmediagroup.it/
sabato 29 maggio 2010
Siti vs. applicazioni
sabato 29 maggio 2010
Business logic
Web AJAXBase dati
ORM
XML
/
JSON
Object-relationalimpedance mismatch
domain objects / GUIimpedance mismatch
!!
RDBMSvs. objects
domain objects vs. GUI
sabato 29 maggio 2010
HTML✗
sabato 29 maggio 2010
Personalizzazioni?
sabato 29 maggio 2010
Stampe?
sabato 29 maggio 2010
La storia
sabato 29 maggio 2010
Stansabato 29 maggio 2010
Il progetto
sabato 29 maggio 2010
Il progetto
15 processiamministrativi
sabato 29 maggio 2010
Il progetto
15 processiamministrativi
200+ formsWeb
sabato 29 maggio 2010
Il progetto
15 processiamministrativi
190 reports e forms PDF
200+ formsWeb
sabato 29 maggio 2010
Il progetto
15 processiamministrativi
190 reports e forms PDF
200+ formsWeb
sabato 29 maggio 2010
sabato 29 maggio 2010
2 sviluppatori
sabato 29 maggio 2010
2 designers2 sviluppatori
sabato 29 maggio 2010
2 mesi2 designers2 sviluppatori
sabato 29 maggio 2010
sabato 29 maggio 2010
GenroPy
sabato 29 maggio 2010
sabato 29 maggio 2010
Bags
sabato 29 maggio 2010
Bags
gerarchica ed ordinatasimile a XML
valori ed attributi
sabato 29 maggio 2010
Bags
gerarchica ed ordinatasimile a XML
valori ed attributi
lazy loadingdinamica
observer pattern
sabato 29 maggio 2010
Bags
gerarchica ed ordinatasimile a XML
valori ed attributi
lazy loadingdinamica
observer patterndatabase
versatilefiles XML directory trees
web services
sabato 29 maggio 2010
Bags
gerarchica ed ordinatasimile a XML
valori ed attributi
lazy loadingdinamica
observer pattern
base datiuniversale
interfaccia utente
domain specific languages
databaseversatile
files XML directory trees
web services
sabato 29 maggio 2010
Business
Logic
Web AJAXBase dati
ORM
XML
/
JSON
PDFBags
sabato 29 maggio 2010
Database
sabato 29 maggio 2010
Quasi un ORM...
class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...
sabato 29 maggio 2010
Quasi un ORM...
class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...
tbl.column('id',size='22',group='_',readOnly='y',name_long='Id')
sabato 29 maggio 2010
Quasi un ORM...
class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...
validate_notnull=True,validate_notnull_error='!!Mandatory field'
sabato 29 maggio 2010
Quasi un ORM...
class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...
tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name')
sabato 29 maggio 2010
Quasi un ORM...
class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...
def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...
sabato 29 maggio 2010
GUI
sabato 29 maggio 2010
HTML✗
sabato 29 maggio 2010
Dojo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
AJAX semplicissimo
sabato 29 maggio 2010
sabato 29 maggio 2010
Package(s)
sabato 29 maggio 2010
Istanze
Package(s)
sabato 29 maggio 2010
Siti
Istanze
Package(s)
sabato 29 maggio 2010
Siti
Istanze
Package(s)
GUI
Database
Risorse
sabato 29 maggio 2010
Siti
Istanze
Package(s)
GUI
Database
Risorse
Mixin
sabato 29 maggio 2010
Siti
Istanze
Package(s)
GUI
Database
Risorse
Mixin
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
sabato 29 maggio 2010
Siti
Istanze
Package(s)
GUI
Database
Risorse
Mixin
class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'
def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()
def rpc_dammi_ora(self): return Bag('http://www.example.com/websvc/get_time')['Europe.Rome']
sabato 29 maggio 2010
Stampe
sabato 29 maggio 2010
sabato 29 maggio 2010
Codice
sabato 29 maggio 2010
Editor PDFCodice
sabato 29 maggio 2010
Il progettoatto II
sabato 29 maggio 2010
User
Inserimento dati tramite form Web
Inserimento dati tramite form PDF
Stampa ed archiviazione
Utente
sabato 29 maggio 2010
sabato 29 maggio 2010
m4.py (mixin)
Componenti
fascicolo.py (webpage)
form richiesta
formato dati PDF
azioni pre / post
elementi GUI condivisi nelle forms
GUI comune
communicazione con PDF
sabato 29 maggio 2010
class Table(object):
def config_db(self, pkg): tbl = pkg.table('documento', pkey='id',name_long='!!Documento', name_plural='!!Documenti', rowcaption="$descrizione") self.sysAndComuneIdFields(tbl) tbl.column('fascicolo',name_long='!!Fascicolo') tbl.column('modello',name_long='!!Modello') tbl.column('data','D',name_long='!!Data del documento') tbl.column('ts_richiesta','DH',name_long='!!Data e ora') tbl.column('dati_richiesta','X',group='_',name_long='!!Dati richiesta', _sendback=True) tbl.column('dati_pdf','X',group='_',name_long='!!Dati del documento PDF') tbl.column('descrizione',name_long='!!Descrizione') tbl.column('user_id',size='22',group='_', _sendback=True).relation('adm.user.id',mode='foreignkey',onDelete='cascade',deferred=True, one_one=True)
Tabella “documento”
sabato 29 maggio 2010
class Table(object):
def config_db(self, pkg): tbl = pkg.table('documento', pkey='id',name_long='!!Documento', name_plural='!!Documenti', rowcaption="$descrizione") self.sysAndComuneIdFields(tbl) tbl.column('fascicolo',name_long='!!Fascicolo') tbl.column('modello',name_long='!!Modello') tbl.column('data','D',name_long='!!Data del documento') tbl.column('ts_richiesta','DH',name_long='!!Data e ora') tbl.column('dati_richiesta','X',group='_',name_long='!!Dati richiesta', _sendback=True) tbl.column('dati_pdf','X',group='_',name_long='!!Dati del documento PDF') tbl.column('descrizione',name_long='!!Descrizione') tbl.column('user_id',size='22',group='_', _sendback=True).relation('adm.user.id',mode='foreignkey',onDelete='cascade',deferred=True, one_one=True)
Tabella “documento”
sabato 29 maggio 2010
class Table(object):
def config_db(self, pkg): tbl = pkg.table('documento', pkey='id',name_long='!!Documento', name_plural='!!Documenti', rowcaption="$descrizione") self.sysAndComuneIdFields(tbl) tbl.column('fascicolo',name_long='!!Fascicolo') tbl.column('modello',name_long='!!Modello') tbl.column('data','D',name_long='!!Data del documento') tbl.column('ts_richiesta','DH',name_long='!!Data e ora') tbl.column('dati_richiesta','X',group='_',name_long='!!Dati richiesta', _sendback=True) tbl.column('dati_pdf','X',group='_',name_long='!!Dati del documento PDF') tbl.column('descrizione',name_long='!!Descrizione') tbl.column('user_id',size='22',group='_', _sendback=True).relation('adm.user.id',mode='foreignkey',onDelete='cascade',deferred=True, one_one=True)
Tabella “documento”
sabato 29 maggio 2010
class Personale(BaseComponent):
py_requires="elezforms:BaseElezForms" def formPersonale(self, pane, **base_kwargs): kwargs = {'width': '100%', 'border_spacing': '4px'} kwargs.update(base_kwargs) fb = pane.formbuilder(cols=2, dbtable="comune.personale", **kwargs) fb.field('num') fb.field('nominativo', autospan=1) fb.field('data_nas', autospan=1) fb.field('qualifica', autospan=1) fb.field('categoria', autospan=1) fb.field('ufficio', autospan=1) fb.field('num_ore', autospan=1) fb.field('incarico', autospan=1) return fb
Componenti
sabato 29 maggio 2010
class Personale(BaseComponent):
# ... continua ... def selezionaMoltiPersonale(self, parentBC, **base_kwargs): kwargs = dict( label="Personale", basename="personale", table="comune.personale", selectionPars=dict(order_by="nominativo")) kwargs.update(base_kwargs) self.selezionaMolti(parentBC, **kwargs) def personale_struct(self, struct): r = struct.view().rows() r.fieldcell("num", width="4em") r.fieldcell("nominativo", width="15em") r.fieldcell("data_nas", width="8em", format_fullYear=True) r.fieldcell("categoria", width="10em") r.fieldcell("ufficio", width="15em") return struct
Componenti
sabato 29 maggio 2010
class Modulo(object):
def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]
def abilitaCompilazioneGuidata(self): return True
def enableSaveDatiPdf(self): return False
def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")
def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")
def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))
Mixin
sabato 29 maggio 2010
class Modulo(object):
def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]
def abilitaCompilazioneGuidata(self): return True
def enableSaveDatiPdf(self): return False
def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")
def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")
def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))
def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")
Mixin
sabato 29 maggio 2010
class Modulo(object):
def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]
def abilitaCompilazioneGuidata(self): return True
def enableSaveDatiPdf(self): return False
def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")
def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")
def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))
def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id",multiple=True))
Mixin
sabato 29 maggio 2010
class Modulo(object):
def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]
def abilitaCompilazioneGuidata(self): return True
def enableSaveDatiPdf(self): return False
def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")
def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")
def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))
Mixin
sabato 29 maggio 2010
class Modulo(object):
def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]
def abilitaCompilazioneGuidata(self): return True
def enableSaveDatiPdf(self): return False
def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")
def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")
def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))
def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaSezione(bc, storeRecord="#dati_richiesta.sezione", label="Seleziona la sezione")
def formatoDatiPdf(self, root): sez = root.sezione(onLoad=self.creaRecord(datapath='dati_richiesta.sezione')) sez.attestazione(onLoad=self.selezionaRecord(where='$comune_id = :comune_id and $sezione_id = :sezione_id and not fuori_comune', sezione_id='=parent.id', order_by='$sesso,$nominativo', multiple=True))
Mixin
sabato 29 maggio 2010
RSS Reader
sabato 29 maggio 2010
#!/usr/bin/env pythonw# -*- coding: UTF-8 -*-## untitled## Created by Giovanni Porcari on 2007-03-24.# Copyright (c) 2007 Softwell. All rights reserved.#
""" RSS READER """from gnr.core.gnrbag import Bag
class GnrCustomWebPage(object): maintable='rss.feed' css_require='rssreader' def pageAuthTags(self, **kwargs): return 'user' def main(self, root, **kwargs): layout = root.borderContainer(design="sidebar") self.left(layout.borderContainer(region='left', width="30%", splitter=True, _class='fakeclass',datapath='feed')) self.top(layout.contentPane(region='top',height='30%', splitter=True,_class='fakeclass')) center = layout.stackContainer(region='center',_class='fakeclass',selectedPage='^rss.page') center.contentPane(pageName='loading').div('...Loading...') center.contentPane(pageName='loaded').iframe(height='100%',width='100%', delay=2000,border='0', onUpdating='genro.setData("rss.page","loading");', onLoad='genro.setData("rss.page","loaded");', src='^rss.link') def left(self,bc): self.feedform(bc.contentPane(region='top',_class='fakeclass')) center = bc.contentPane(region='center',_class='fakeclass') center.tree(storepath='.tree',labelAttribute='caption',selected_k_id='.curr.pkey', selected_k_url='.curr.url',_fired='^.refreshTree', inspect='shift') center.dataRpc('.tree','getFeeds',_fired='^.refresh',_onResult='FIRE .refreshTree',_onStart=True) center.dataRpc('rss.rows','getItems',url='^.curr.url',_if='url',_else="null")
def feedform(self,pane): fb = pane.formbuilder(cols=2,border_spacing='4px',datapath='.record',formId='rss', controllerPath='form',pkeyPath='feed.curr.pkey', width='90%',dbtable='rss.feed') #fb.textbox(value='^.topic',lbl='!!Topic',width='100%') #fb.textbox(value='^.title',lbl='!!Title',width='100%') #fb.textbox(value='^.url',lbl='!!Address',colspan='2',width='100%') fb.field('topic',autospan=1) fb.field('title',autospan=1) fb.field('url',autospan=2) fb.button('!!Save',action="genro.formById('rss').save();", disabled='==!_valid',_valid='^form.valid') fb.button('!!New',action="FIRE feed.curr.pkey='*newrecord*';") # == ritorna un espressione javascript pane.dataController(""" genro.formById('rss').load({destPkey:destPkey});""", destPkey='^.curr.pkey',_onStart=True) pane.dataRpc('.savedId','saveFeed',record='=.record', _onResult=""" genro.formById('rss').saved(); FIRE .refresh;""",nodeId='rss_saver') pane.dataRecord('.record','rss.feed',pkey='=.curr.pkey',nodeId='rss_loader', _onResult="genro.formById('rss').loaded()") def rpc_saveFeed(self,record=None,**kwargs): tblfeed = self.db.table(self.maintable) if not record['id']: record['username'] = self.user tblfeed.insert(record) else: tblfeed.update(record) self.db.commit() return record['id'] def rpc_getFeeds(self): results = self.db.table(self.maintable).getFeeds(user = self.user) return results
def rpc_getItems(self,url=None,**kwargs): rss=Bag(url)['rss.channel'].digest('#v') rows = Bag() for i,item in enumerate(rss): if isinstance(item,Bag): rows.setItem('n_%i' %i,None,title=item['title'],link=item['link'],description=item['description']) return rows def item_struct(self): struct = self.newGridStruct() r = struct.view().rows() r.cell('title', name='!!Title', width='20em',classes='titleCell') r.cell('description', name='!!Description', width='50em',classes='descCell') return struct def top(self,pane): pane.includedView(storepath='rss.rows', nodeId='rssItemsGrid',autoWidth=True, selected_link='rss.link', struct=self.item_struct())
RSS Reader
109 righe
sabato 29 maggio 2010
Presente Futuro
sabato 29 maggio 2010
Futuro
Community, Community, Community
sabato 29 maggio 2010
Grazie!
Roberto Lupi
[email protected]://www.medmediagroup.it/
GenroPyhttp://www.genropy.org/
http://blog.lupi-software.com/http://svn.genropy.org/genro/trunk
@robertolupi
sabato 29 maggio 2010