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>






