mercoledì 8 dicembre 2010

Python e Ajax con JSON su Apache

Salve a tutti!!
In questo post voglio illustrarvi come far interagire il browser con un applicativo per il web sviluppato con python tramite il mod_python di apache.
Iterazione che deve essere asincrona quindi con Ajax "puro". Lo scambio dei dati avviene sfruttando oggetti JSON pattern supportato nativamente sia da python che da javascript.

Nel tentare di illustrarvi un possibile uso modificheremo l'applicativo trattato nel precedente post in cui parlavo di python dedicato al web. Post che vi suggerisco di leggere, capire e testare se no non capirete le modifiche che apporteremo anche perchè alcune parti del codice le ometterò facendo riferimento solo al file.
Prima ho sottolineato puro perchè anche in questo caso non useremo frameworks javascript come jQuery o roba simile ma solo javascript scritto a manella che in realtà ho scopiazzato dalla rete ;) Non sono bravo in javascript dato che ci metto mano pochissime volte, ma come diceva un mio professore di informatica alle superiori ".. se si hanno le basi, per imparare un nuovo linguaggio basta un manuale del linguaggio, un vocabolario della lingua inglese, e due settimane di tempo...." io le due settimane le ho ridotte googlando :D

Comunque la modifica consiste nel rendere ordinabile la tabella contenente la lista delle dediche in base al tipo di informazione contenuta nel nome della colonna e quini clikkando su di essa il tutto tramite Ajax e JSON.

Il meccanismo di funzionamento è il seguente:
1. L'utente clicca sul nome di colonna per ordinare ad esempio per Nickname.
2. Tramite Ajax viene chiamato un servizio python del modulo index.py
3. index.py riprende i dati dal db ordinati per nickname
4. restituisce i dati alla chiamata Ajax.
5. ricevuti i dati in javascript si svuota e si riempie la tabella.

Per fare ciò abbiamo bisogno di fare modifiche al model al view e al controller (che se avete letto il post che vi ho inicato sopra saprete di cosa sto parlando).

Model:
se ricordate il file DedicaDAO.py aveva il metodo findAll che si occupava di recuperare tutti gli oggetti di tipo dedica dal db solo che recuperava i dati sempre ordinati per data inserimento, bene per adattarlo ai nostri scopi dobbiamo renderlo parametrico. Sostituite quindi quello precedente con il seguente pezzo di codice:



non c'è bisogno di spiegarvi quale è stata la modifica vero?

Per generare gli oggetti JSON da passare in risposta useremo il modulo python 'json' che è gia presente nella sua installazione di base. In particolare usermo una sua funzione (dumps) che però accetta solo dizionari e liste (che come vedrete la sintassi python per tali strutture è quasi identica a JSON).

Infatti se vogliamo rappresentare un oggetto json di dedica ecco come è fatto:


{"messaggio": "Ciao Mondo!!!!!!!!!!!", "nickname": "Piergiuseppe", "id": 20, "dataInserimento": "21-11-2010 18:12:17", "email": "piergiuseppe82@yahoo.it"}

Che vi ricorda? Un dizionario Python.

Chiudiamo la parentesi della somiglianza e aggiungiamo il metodo toDict() alla classe Dedica.py:



come vedete la data va trasformata in stringa altrimenti quanto passeremo le varie istanze di dedica la metodo del modulo json di python andrà in errore. Questo perchè non supporta gli oggetti datetime

Controller
Per quanto riguarda il controller ossia il nostro file index.py dobbiamo aggiungere solo il nuovo metodo che sarà usato per fornire gli oggeti JSON alla chiamata Ajax, ecco il metdo:

Il metodo come vedete piglia come parametro l'ordinamento che per default è "dataInserimento" quindi carica i dati dal model con un findAll del dao (riga 5). Ricevute le dediche prepara una nuova lista vuota e la carica con un dizionario per ogni oggetto dedica (righe 8 e 9) e restituisce la lista di oggetti json trasformando la lista contenente i dizionari con l'istruzione json.dumps() (riga 10)

Come vede è facile creare oggetti json in python.

In realtà potete già testare tale servizio. Anzi fatelo così stiamo sicuri che lato server della comunizione Ajax è tt ok. Per farlo deployate i files modificati su apache e chiamate il seguente url:

http://localhost/PyGuestbook/index.py/ajax_dediche

il risultato nel browser dovrebbe essere simile al seguente (ovviamente se avete già inserito dediche sul db con la precedente versione dell'applicativo):


[
{"messaggio": "Ciao Mondo!!!!!!!!!!!", "nickname": "Piergiuseppe", "id": 20, "dataInserimento": "21-11-2010 18:12:17", "email": "piergiuseppe82@yahoo.it"},
{"messaggio": "Ciao!!!!!!!!!!!!!!", "nickname": "Piergiuseppe82", "id": 21, "dataInserimento": "21-11-2010 18:12:46", "email": "piergiuseppe82@yahoo.it"},
{"messaggio": "ssssssssssssssssssssssss", "nickname": "aldo", "id": 22, "dataInserimento": "08-12-2010 19:14:34", "email": "aldo@mail.it"},
{"messaggio": "zzzzzzzzzzzzzzzzzzzzzzzzzzz", "nickname": "franco", "id": 23, "dataInserimento": "08-12-2010 19:56:05", "email": "franco@mail.it"}
]

Ossia una lista di oggetti json.
View
Abbiamo detto che quando l'utente clicca su una colonna deve scatenarsi una chiamata ajax per ottenere gli oggetti json giusto? Allora ecco come deve essere modificata la psp che visualizza la lista delle dediche; listaDediche.psp:


Il contenuto è come il precedente in più abbiamo aggiunto i tag "thead" e "tbody"  identificando quest'ultimo con l'id "tbDedicheBody". Sfrutteremo tale soluzione per ripopolare solo il body della tabella tramite javascript. Ovviamente abbiamo reso dei link i nomi delle colonne i quali puntano alla funzione javascript che si occupa della chiamata ajax e del ripopolamento. Guardiamo uno a caso da vicino:

Come vede è un link che punta al servizio che abbiamo inserito nel controller il quale link viene passato alla funzione javascript "caricaDediche()" insieme all'ordinamento scelto (in questo caso nickname).

Le funzioni javascript le mettiamo in due files uno che contiene le funzioni per la comunicazione ajax e un'altro quelle dedicate al popolamento della tabella.

Quindi create una cartella js (nella stesa directory di index.py o dove vi pare) e inserite i seguenti files:

ajax.js:


il codice che vedete l'ho preso da un post su html.it e che consiglio di leggere per capire cosa fa il codice. Esso mette a disposizione due funzioni entrambe cross-browser una ci fornisce l'XmlHttpRequest adatto al browser oggetto necessario per le chiamate ajax e delle costanti testuali da utilizzare per facilitare la gestione delle chiamate, l'altro gli elementi del DOM per id.

dediche.js:


Anche questo l'ho fatto scopiazzando codice qua e là.
La funzione caricaDediche inizia alla riga 51 e come vede piglia come parametri nome del file da richiamare e orinamento. Vediamo cosa fa la funzione. Dopo aver ricevuto i parametri recupera l'oggetto XmlHttpRequest (r.54) apre la connesione (r.62) notatte qui che il tipo di ordinamento viene passato in get appendendolo come parametro all'url. Dopo aver aperto la connessione alla riga 68 si mette in ascolto  sui cambiamenti di stato di quest'ultima. Appena raggiunge lo stato completato e l'esito è positivo (r. 71-73)  trasforma il testo ricevuto in oggetti json (r.75), quindi ripulisce il corpo della tabella. Poi per ogni oggetto json restituito ne costruisce il codice html per i link di modifica e eliminazione  (r. 79 - 80)  e aggiunge la riga alla tabella (r. 81) .
Da notare come si accede agli attributi dell'oggetto json ossia obj.id obj.messaggio che se notate sono i gli stessi nomi che abbiamo dato al dizionario python.

Bene l'ultima modifica è includere i file javascript nell'heder dell'html generato dal mod_python quindi aprite il file header.psp e aggiungete fra i tag "head"   il seguente codice html:



Non vi rimane che deployare e testare.

Non ho spiegato tt il java script perchè non è nello scopo del post.. che come ho già detto è quello di illustrare un possibile utilizzo di python per la generazione di oggetti JSON da utilizzare in chiamate asincrone client-server tramite http.

Comunque pensate ora i possibili utilizzi di python per framework utilizzati nello sviluppo di Rich Internet application primo fra tutti GWT di Google. Io mi sa che un pensierino di provare tale accoppiata lo faccio. E se ne esce qualcosa di buono ve la posto.

Se clikkate qui trovate il sorgente del progetto eclipse

Be ho finito mi vado a bere una (o più)  GUINNESS!!! Alla prossima!!!!

Nessun commento:

Posta un commento