Webpy comunicación en AJAX

Éste es un pequeño How-to en el que vamos a aprender cómo se realiza una comunicación asíncrona entre nuestra base de datos y nuestro aplicativo web. Usando PostgreSQLAJAX y Web.py.

La idea es tener una base de datos en PostgreSQL donde tengamos una tabla con los países de todo el mundo, luego extraer esta tabla con python y convertirla en una salida XML que la enviaremos a las peticiones hechas por AJAX.

Web.py, Python y XML.

Para desarrollar este apartado he creado una base de datos en PostgreSQL llamada “myweb“. En la cual crearemos nuestra tabla “pais“.

1. Creamos nuestra Tabla “pais“:

 CREATE TABLE pais( id serial, codigo char(3), descrip varchar(50) NOT NULL UNIQUE, ubicacion point, PRIMARY KEY (codigo));

Seguidamente debemos hacer INSERT para agregar algunos datos a nuestra tabla de países. Con la carga nos debe quedar algo como esto:

 myweb=# SELECT * FROM pais;
 id| codigo |                     descrip                     | ubicacion
 -----+--------+-------------------------------------------------+-----------
 1 | 013    | AFGANISTAN                                      |
 2 | 017    | ALBANIA                                         |
 3 | 023    | ALEMANIA                                        |
 4 | 026    | ARMENIA                                         |
 5 | 027    | ARUBA                                           |
 6 | 029    | BOSNIA-HERZEGOVINA                              |
 7 | 031    | BURKINA FASSO                                   |

2. Creamos un fichero app.py para obtener todos los paises y mostrarlos en la web con web.py:

 1 #!/usr/bin/env python
 2 # -*- conding: UTF-8 -*-
 3
 4 import web
 5
 6 urls = (
 7         '/', 'home'
 8       )
 9
 10 db = web.database(dbn='postgres', user='postgres', pw='qwerty', db='myweb')
 11
 12 app = web.application(urls, globals())
 13
 14 class home:
 15     def GET(self):
 16         paises = db.select('pais') # Obtenemos todos los países de la DB
 17         return ["codigo: %(codigo)s, nombre: %(descrip)s" % pais
 18                 for pais in paises if pais['descrip']]
 19
 20
 21 if __name__ == "__main__": app.run()

Ejecutemos nuestro App: $ python app.py

Hasta este punto solo hemos demostrado que existe comunicación para nuestro CGI.

Ahora podemos crearnos una nueva URL y una clase llamada “pais” para que nuestros clientes puedan extraer un documento XML con todos los paises de nuestra base de datos:

 5 urls = (
 6         '/', 'home',
 7         '/paises', 'pais'
 8       )

Clase para la tabla pais:

 21 class pais:
 22     def GET(self):
 23         import dbToXML
 24
 25         xml = dbToXML.dbToXML(db, ('pais',), ('codigo', 'descrip'))
 26         return xml.xmldoc.toxml()

Miremos qué resultado obtenemos si ingresamos a: http://127.0.0.1:8080/paises

Como habrás notado el módulo dbToXML no existe en tu árbol de Python, es posible que tengas que descargarlo de https://github.com/jolth/Add-On_Web.py. Es muy fácil de usar y de leer el código.

La idea en este punto, es que nuestros usuarios puedan solicitar la URL http://127.0.0.1:8080/paises y obtengan un documento XML válido con la estructura:

 <?xml version="1.0" ?>
 <pais>
  <content>
   <codigo>013</codigo>
   <descrip>AFGANISTAN</descrip>
  </content>
  <content>
   <codigo>017</codigo>
   <descrip>ALBANIA</descrip>
  </content>
 [... corte ...]
 </pais>

AJAX.

Ya tenemos todo listo para que nuestro CGI responda a las peticiones hechas y retorne un fichero XML válido. Es solo cuestión de construir la comunicación asíncrona (Ajax), en una plantilla e incluir el sistema de plantillas en nuestro App. Así:

1. Plantilla:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>Consulta de Paises</title>
 5     <script>
 6         var READY_STATE_COMPLETE = 4;
 7
 8         function carga(){
 9             var req = new XMLHttpRequest();
 10
 11
 12             if(req){
 13
 14                 req.onreadystatechange = muestra;
 15
 16                 req.open("GET", "/paises", true);
 17                 req.send(null);
 18             }
 19
 20             function muestra() {
 21                 if(req.readyState == READY_STATE_COMPLETE){
 22                     if(req.status == 200){
 23                         var xmldoc = req.responseXML;
 24                         /*
 25                            Obtener los datos del Objeto Document
 26                            del XML usando el DOM
 27                          */
 28                         var raiz = xmldoc.getElementsByTagName('pais')[0]; // Obtenemos la raíz del documento <pais></pais>.
 29
 30                         var salida = document.getElementById('salida'); // Obtenemos el elemento donde mostramos la salida
 31                         var htmldoc = "<table>";
 32                         for (var indice=0; indice < raiz.childNodes.length; indice++){
 33                             htmldoc = htmldoc + "<tr>";
 34                             htmldoc = htmldoc + "<td>" + raiz.childNodes[indice].firstChild.childNodes[0].nodeValue + "<\/td>"; // <codigo></codigo>
 35                             htmldoc = htmldoc + "<td>" + raiz.childNodes[indice].lastChild.childNodes[0].nodeValue + "<\/td>"; // <descrip></descrip>
 36                             htmldoc = htmldoc + "<\/tr>";
 37                         }
 38
 39                         htmldoc = htmldoc + "<\/table>";
 40                         salida.innerHTML = htmldoc;
 41
 42                     }
 43                 }
 44             }
 45         }
 46
 47         window.onload = function(){
 48             document.getElementById('boton').onclick = carga;
 49         }
 50     </script>
 51 </head>
 52 <body>
 53     <div>
 54         <button type="button" id="boton">Obten Paises</button>
 55     </div>
 56     <div id="salida"></div>
 57 </body>
 58 </html>

2. y nuestro App tendría el siguiente aspecto:

  1 #!/usr/bin/env python
  2 # -*- conding: UTF-8 -*-
  3 import web
  4 
  5 render = web.template.render('./')
  6 
  7 urls = (
  8         '/', 'home',
  9         '/paises', 'pais'
 10       )
 11 
 12 db = web.database(dbn='postgres', user='postgres', pw='qwerty', db='myweb')
 13 
 14 app = web.application(urls, globals())
 15 
 16 class home:
 17     def GET(self):
 18         return render.index()
 19 
 20 
 21 class pais:
 22     def GET(self):
 23         import dbToXML
 24 
 25         xml = dbToXML.dbToXML(db, ('pais',), ('codigo', 'descrip'))
 26         web.header('Content-Type', 'text/xml')
 27         return xml.xmldoc.toxml()
 28 
 29 
 30 if __name__ == "__main__": app.run()
 31

Listo, ejecutemos y obtendremos una limpia comunicación asíncrona en Web.py con AJAX.

$ python app.py

Aquí solo trato de mostrar un concepto que para muchos es complicado y que ya con esto es solo cuestión de imaginación para lograr grandes efectos como: autocompletado, búsquedas, listas desplegables, etc.

Autor: Jolth

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s