developer.cl desarrollo, gestión y otras cosas acerca de proyectos de software

22Jun/090

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:

Arbol de Proyectos

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>

¿Te gustó este artículo?

¡Suscríbete a nuestro feed RSS!

Acerca de lcruz

Sin descripción. Por favor completa tu perfil.
Comentarios (0) Trackbacks (0)

Aún no hay comentarios.


Deja un comentario


Aún no hay trackbacks.