Extendiendo manage.py para sincornizar con Flex
Estamos haciendo un sistema que tendrá como interfaces algunas pantallas en Flex por lo que ha surgido la necesidad de publicar algunos servicios remotos utilizando PyAMF. En Flex utilizamos Cairngorm como MVC, este requiere la definición de un archivo de servicios Services.xml que estoy intendando generar utilizando Python y que mejor que hacerlo utilizando el mismo estilo que utiliza DJango para la sincronización de la base de datos. Por ello estoy intenando generar una opción nueva el comando manage.py de la aplicación DJango:
manage.py syncflex
Gracias a la flexibilidad de DJango esto es bastante fácil nada más debes crear una clase que debes llamar Command que extienda a la clase BaseCommand y ubicarla en paquete managment/commands bajo alguna de tus aplicaciones en mi caso yo estoy haciendo un pequeño ERP así que la ubique en la ruta flex/managment/commands:

En mi caso dado que mi comando no tiene argumentos extendere la clase NoArgsCommand :
class Command(NoArgsCommand): help = "Sync Flex Commands" requires_model_validation = False def handle_noargs(self, **options): # Your code here
El método handle_noargs es el que nos permite ejecutar las acciones realizadas por nuestro comando cuando es invocado, en mi caso la implementación es la siguiente (algo básica por ahora):
def handle_noargs(self, **options): from pyamf.remoting.gateway.django import DjangoGateway import sys project = settings.ROOT_URLCONF.split('.')[0] #import types for app in models.get_apps(): if project == app.__name__.split('.')[0]: app_name = app.__name__.split('.')[-2] package = project + '.' + app_name + '.gateway' try: mod = __import__(package, globals(), locals(), ['gateway'], -1) for d in dir(mod): attr = getattr(mod, d) try: if isinstance(attr, DjangoGateway): self.processClass(d, attr) except TypeError: pass except ImportError: pass
Como se puede ver su funcionamiento se basa en introspección, para ello busco un módulo llamado gateway dentro de mis aplicaciones DJango una vez que encuentro el módulo busco en él las clases que extiendan a DjangoGateway para generar el archivo Services.xml. Un ejemplo de mi archivo gateway.py es:
from pyamf.remoting.gateway.django import DjangoGateway from django.contrib.auth.models import User from sampleapp.contabilidad.models import Comprobante from sampleapp.gateway.amf import AMFGateway class ComprobanteGateway(AMFGateway): def obtenerComprobantes(self, request, data): # Implemetnar pass class CuentaGateway(AMFGateway): def obtenerCuentas(self, request, data): # Implemetnar pass contabilidadGateway = DjangoGateway({'gwComprobante' : ComprobanteGateway, 'gwCuenta' : CuentaGateway,})
Si vemos la implementación del método processClass tenemos lo siguiente:
def processClass(self, name, gateway): import inspect print ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<cairngorm:ServiceLocator xmlns:mx=\"http://www.adobe.com/2006/mxml\"" "xmlns:cairngorm=\"com.adobe.cairngorm.business.*\">\n") for g in gateway.services: print ("<mx:RemoteObject id=\"" + g + "\" " "\n\t\tdestination=\"" + g + "\" " "\n\t\tendpoint=\"" + settings.REMOTING_URL + "/" + name + "\" " "\n\t\tshowBusyCursor=\"true\" " "\n\t\tresult=\"event.token.resultHandler( event );\" " "\n\t\tfault=\"event.token.faultHandler( event );\">") service = gateway.services[g] for m in service.getMethods(): print "\t<mx:method name=\"" + m + "\" />" print "</mx:RemoteObject>\n" print "</cairngorm:ServiceLocator>"
Con eso ya estamos casí listos sólo nos falta agregar nuestra aplicación para que DJango la conozca y definir la variable REMOTING_URL para ello sólo editamos nuestro archivo settings.py:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'sampleapp.contabilidad', 'sampleapp.compra', 'sampleapp.agricola', 'sampleapp.rrhh', 'sampleapp.maquinaria', 'sampleapp.comun', 'sampleapp.actividad', 'sampleapp.flex', ) # -------------------------------------------------- # My customs settings # -------------------------------------------------- REMOTING_URL = "http://localhost:8080/remoting"
Con eso ya estamos listo ahora sólo ejecutamos manage.py syncflex en la consola:
manage.py syncflex
Aquí una muestra del resultado:
<?xml version="1.0" encoding="utf-8"?> <cairngorm:ServiceLocator xmlns:mx="http://www.adobe.com/2006/mxml"xmlns:cairngorm="com.adobe.cairngorm.business.*"> <mx:RemoteObject id="gwCuenta" destination="gwCuenta" endpoint="http://localhost:8080/remoting/contabilidadGateway" showBusyCursor="true" result="event.token.resultHandler( event );" fault="event.token.faultHandler( event );"> <mx:method name="obtenerCuentas" /> </mx:RemoteObject> <mx:RemoteObject id="gwComprobante" destination="gwComprobante" endpoint="http://localhost:8080/remoting/contabilidadGateway" showBusyCursor="true" result="event.token.resultHandler( event );" fault="event.token.faultHandler( event );"> <mx:method name="obtenerComprobantes" /> </mx:RemoteObject> </cairngorm:ServiceLocator>
Complementos de búsqueda con OpenSearch
Hace poco escribí algunas extensiones utilizando OpenSearch. OpenSearch es un conjunto de estándares que permiten la publicación de los resultados de los sistemas de búsqueda permitiendo de este modo la sindicación y la agregación de contenidos entre diferentes motores y sistema de búsqueda. OpenSearch se compone de 3 partes, un formato para la descripción de motores de búsqueda, un formato para la descripción de los resultados de búsqueda llamado OpenSearch Response y finalmente los agregadores o sitios capaces de mostrar resultados en formato OpenSearch.
Navegadores como IE7 y Firefox soportan ya OpenSearch, es decir, permiten la incorporación de complementos de búsqueda mediante este estándar, al mismo tiempo cada uno de estos navegadores extiende las capacidades estándares de OpenSearch agregándole sus propios sabores.
La utilización de OpenSearch permite incorporar algo de usabilidad a tus sitios Web, si es que, los mismos presentan buscadores a los usuarios. Yo en mi caso particular utilizo un diccionario en inglés de la empresa WordMagic, este diccionario presenta un buscador en su portada mediante el cuál puedes acceder a las palabras del diccionario. Dado que a mí me resultaba bastante molesto ingresar al sitio para realizar la búsqueda es que me decidí a hacer este complemento, además es muy sencillo hacerlo y lo puedes incorporar también en tus sitios. A continuación veremos este ejemplo:
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/"> <ShortName>WordMagic</ShortName> <Description>Word Magic Software, Inc. es una compañia dedicada al desarrollo de software con sede en Houston, Texas.</Description> <InputEncoding>UTF-8</InputEncoding> <Image width="16" height="16" type="image/x-icon">http://wordmagicsoft.com/favicon.ico</Image> <Url type="text/html" method="POST" template="http://wordmagicsoft.com/diccionario/search.php"> <Param name="word_to_search" value="{searchTerms}"/> <Param name="search_option" value="es-en"/> </Url> </OpenSearchDescription>
Los parámetros especificados son los siguientes:
- OpenSearchDescription: Este es el nodo principal de un documento OpenSearch.
- ShortName: Un pequeño titulo que identifique al buscador.
- Description: Una descripción más larga acerca del buscador.
- InputEncoding: El encoding que soporta nuestro el buscador.
- Image: La url de algún icono representativo de nuestro buscador.
- URL: Describe la interfaz para nuestro buscador, o sea aquella que responderá a las búsquedas. El atributo template permite especificar la url y el atributo method permite indicar si se hará un GET o un POST a la url.
Eso es todo! Guardamos el contenido en un archivo xml, en mi caso le puse wordmagic.xml y ya esta! ahora solo nos queda agregarlo a nuestro navegador, para ello utilizaremos un pequeño javascript, para ello puedes construirte una página con lo siguiente:
<SCRIPT LANGUAGE="JavaScript"> <!-- function addWordMagicSearch() { window.sidebar.addSearchEngine("http://developer.cl/opensearch/wordmagic.xml", "http://wordmagicsoft.com/favicon.ico", "WordMagic", ""); } //--> </SCRIPT>
Luego solo tienes que agregar la llamada en el HTML:
<a href="#" onclick="addWordMagicSearch();">Agregar búsqueda en WordMagic</a>
Mira aquí esta el mio.
Twitter, algo útil despues de todo.
Antes pensaba que twitter era una perdida de tiempo ¿para que diablos alguien seguirá a otros en una especie de reality virtual con sólo 140 caracteres por escena? Ahora lo llevo utilizando una par de días y lo encuentro de una simpleza similar a del.icio.us pero con un potencial de igual magnitud: acceso a información de primera línea, una mirada sobre el hombro de gente que la lleva en determinados temas. Me quede pensando en esto luego de descubrir Watin ojeando twitter. Con una rápida mirada te enteras del diario vivir de gente que consideras un referente, sin quererlo una especie de consejo, un mini-blog, en fin, una herramienta útil para un aprendiz de Jedi como yo.
Watin, mejor que Selenium pero sólo para .NET
Acabo de encontrar a Watin, una herramienta OpenSource para la automatización de pruebas mediante la imitación o grabación de las secuencias de interacción sobre una página Web, según un experto en el tema es mejor que Selenium, al parece su uso es bastante sencillo y soporta Internet Explorer y Firefox. Lamentablemente sirve solo para aplicaciones .NET, así que por ahora no me queda otra que seguir intentando configurar Selenium.






