Noticias sobre mis proyectos

martes, 14 de junio de 2011

El misterio de la variable controller en la definición de rutas

Routes - mapeo de URLs para aplicaciones web

En este artículo les hablaré acerca de una característica del módulo  PyRoutes que al menos yo no encontré bien documentada. Se trata del manejo de la variable controller dentro de la definición de las rutas en una aplicación web. Le invito a continuar leyendo este artículo si quiere conocer qué es lo que hace este módulo, la naturaleza del problema (si es que se le puede llamar así) y cómo se resuelve.

Acerca del módulo PyRoutes

El módulo  Routes ha sido diseñado para resolver un problema muy frecuente en el desarrollo de aplicaciones web, que es cómo relacionar las URLs con acciones concretas. Por ejemplo, blog/2008/01/08 podría mostrar una lista de artículos publicados en cierta fecha, mientras que login se utilizaría para autentificar los usuarios, ... y así sucesivamente.

Es característico de  Routes el poder definir las acciones del sitio y la jerarquía de URLs de forma independiente, para luego enlazarlas del modo que sea más conveniente. Si en algún momento se cambia de idea acerca de una URL solo se cambia la línea donde se define la regla, y no será necesario tocar la definición de la acción. Incluso es posible tener múltiples caminos para lograr el mismo resultado.

El diseño de  Routes ha sido inspirado por  Ruby On Rails, pero en su estado actual existen divergencias significativas. Con el tiempo se ha convertido en la base de frameworks como  Pylons,  CherryPy, y permitió la integración de  TurboGears 2 con  Pylons.

El problema

 Routes forma parte también de un framework  WSGI muy sencillo que desarrollo desde hace poco tiempo. Al utilizarlo siempre me llamó la atención que la documentación ofrecía ejemplos donde se utilizaba la variable controller en la definición de las rutas. Por ejemplo en este caso :

>>> from routes import Mapper
>>> mapper = Mapper()
>>> mapper.connect('test', '/{controller}/{action}')
>>>
>>> print mapper.routematch('/hello/world')
None

Cómo se puede apreciar este código no funciona. Por otra parte , si se cambia ligeramente el código anterior entonces sí funciona.

>>> from routes import Mapper
>>> mapper = Mapper()
>>> mapper.connect('test', '/hello/{action}', controller='hello')
>>>
>>> mapper.match('/hello/world')
{'action': u'world', 'controller': u'hello'}

¿Entonces cuál es la causa de esta situación aparentemente tan extraña?

Utilizando la variable controller en definiciones de rutas

Pues bien la cuestión es que en el Mapper() no se especifican los controladores. Todo parece indicar que hay que hacer esto explícitamente. La implementación predeterminada utiliza los nombres de los ficheros en un directorio. Sucede que por defecto, si no encuentra el controlador adecuado al procesar la ruta siempre se devuelve None. Ese es también el motivo por el que el segundo ejemplo funciona al especificar un controlador.

Para solucionarlo, existen dos opciones:

  1. Pasar a Mapper() la ruta (absoluta) a los controladores
mapper = Mapper(directory='/ruta/a/los/controllers']

  1. Pasar a Mapper() una función controler_scan que devuelva una lista con los nombres de los controladores disponibles. Por ejemplo:
>>> def controller_scan(directory=None):
...        return 'hello', 'auth'
... 
>>> mapper = Mapper(controller_scan=controller_scan)
>>> mapper.connect('default', '/{controller}/{action}')
>>> mapper.connect('login', '/login', controller='auth', action='login')
>>> mapper.connect('logout', '/logout', controller='auth', action='logout')
>>> mapper.match('/hello/world')
{'action': u'world', 'controller': u'hello'}

En mi caso particular, la segunda opción es la más apropiada. Así que muchas gracias  Chema Cortes por  aclararme esta duda ... ;o) Espero que este artículo le sirva a Usted también de referencia y quizás le ahorre un buen tiempo tratando de hacer que esto funcione.

lunes, 6 de junio de 2011

Uso local de Dragonfly para depurar sitios web con Opera

Dragonfly = Firebug para Opera

Escribo este artículo después de descubrir cómo utilizar una herramienta desarrollo tan importante como Dragonfly sin tener que estar conectado a los servidores de Opera. Despúes de haber pasado mucho tiempo creyendo firmemente que la mejor opción era tener algo como su equivalente Firebug por fin he logrado instalarlo y hacerlo funcionar en la PC donde desarrollo aplicaciones web. Todo parece indicar que encontré el checkbox correcto ;o). Si sigue leyendo este artículo hasta el final Usted descubrirá una forma más cómoda de depurar con Opera los errores o defectos de sus aplicaciones. Como siempre le invito a suscribirse mediante RSS a este blog; especialmente si desea estar informado de temas relacionados con programación, diseño de sitios, herramientas o trucos útiles, y muchas otras cosas interesantes del mundo de la informática.

Instalación paso a paso de Dragonfly

El proceso es realmente simple. Lo primero que hay que hacer es descargar la versión más reciente de Dragonfly desde los servidores de Opera.

Descargar Dragonfly

Una vez hecho esto, extraiga los contenidos del fichero .zip en una carpeta en su sistema de archivos local. En este caso, como utilizo Ubuntu 10.04 Lucid, la carpeta que escogí fue /var/www/dragonfly , pero puede ser cualquiera (... donde el usuario tenga derechos de lectura, por supuesto ;o).

Posteriormente, es preciso sobre-escribir la URL desde donde se descargará la herramienta y remplazarla por una que haga referencia a la ubicación de la carpeta creada anteriormente. Hay dos formas de hacerlo. Las describo a continuación .

Editando el fichero operaprefs.ini

La vía más avanzada consiste en editar manualmente el fichero operaprefs.ini (así que si Usted prefiere los diálogos de configuración, mejor consulte el próximo epígrafe ;o) . En Ubuntu 10.04 este fichero se encuentra en la ruta ~/.opera/operaprefs.ini . En Windows la ruta sería C:\Documents and Settings\<Usuario>\Application Data\Opera\Opera\operaprefs.ini. Cuando lo encuentre, utilice el editor de texto de su preferencia para ver sus contenidos. Debe haber un fragmento similar al que se muestra a continuación

[Developer Tools]
Developer Tools URL=https://dragonfly.opera.com/app/

Remplace esta URL por otra de la forma file://localhost/path/to/dragonfly/client-en.xml. En mi caso, como he extraído los ficheros en /var/www/dragonfly, la configuración quedaría así.

[Developer Tools]
Developer Tools URL=file://localhost/var/www/dragonfly/client-en.xml

Utilizando el editor de preferencias de Opera

Si Usted prefiere utilizar diálogos de configuración, sin dudas esta variente es más apropiada. Si Usted está utilizando Opera simplemente haga click en el enlace que se muestra a continuación y verá el editor de preferencias del navegador. Su apariencia es parecida a la que se muestra en la figura.

Editor de preferencias de Opera

URL predeterminada en panel de preferencias de Opera

Remplace la URL (i.e. https://dragonfly.opera.com/app/) por otra de la forma file://localhost/path/to/dragonfly/client-en.xml. En mi caso, como he extraído los ficheros en /var/www/dragonfly, la URL sería file://localhost/var/www/dragonfly/client-en.xml.

URL predeterminada en panel de preferencias de Opera

Posteriormente, presione la combinación de teclas Shift + Ctrl + I e immediatamente aparecerá Dragonfly en la parte baja de la ventana . Poco tiempo después Usted podrá ver las pestañas que permiten observar y manipular el DOM, inspeccionar las peticiones hechas a través de la red, conocer el espacio dedicado al almacenamiento de datos de sesión, ... y así sucesivamente.

Consejos útiles

Si siguió los pasos anteriores, entonces my probablemente ya estará utilizando Dragonfly sin tener que estar conectado a los servidores de Opera. En este caso quizás desee añadir los siguientes botones para facilitar el acceso directo a estas herramientas. Simplemente arrástrelos (drag) y suéltelos (drop) sobre cualquier panel de Opera.

Enlaces directos a Dragonfly

Reload from cache
Dragonfly

En caso que no le funcione algo o tenga dudas en algun paso, simelo pide, podria ayudarle. Espero sus comentarios ;o).