Trabajar sobre la consola
Seguramente para quienes tengan experiencia en lenguajes dinámicos este post les parecerá trivial, para quienes venimos del mundo de los lenguajes estáticos (En mi caso delphi, C++ o C#) la posibilidad de trabajar sobre una consola no esta contemplada, de hecho no existe la posibilidad y tampoco se me hubiese ocurrido como opción.
Siendo python un lenguaje dinámico técnicamente es posible y esta muy bien tener en mente esta idea porque compensa, al menos un poco, las penurias de no tener un compilador hecho y derecho
La idea general
Al trabajar sobre un lenguaje dinámico no tenemos un intelligent code completion decente, tenemos que trabajar mucho con la memoria y ser muy estrictos con la convenciones. Con todo, la memoria tiene limitaciones, la ide puede ayudar pero si tenemos la posibilidad de probar alguna implementacion sobre la marcha se agradece, y como se puede prever la consola lo permite probar ahí, en caliente.
El ejemplo
Para entender la idea imaginemos un ejemplo muy chico, un ejemplo mínimo de un software gastronómico donde se declara la clase"Seleccion", el objeto de la clase puede contener una serie de platos pero no puede contener mas de un plato del mismo tipo, es decir, puede tener, entrada, plato principal, postre, merienda y tanto como se quiera siempre y cuando se cumpla que no existen 2 del mismo tipo (No se agrega al ejemplo la clase Plato, ni la clase TipoPlato, la cual indica su tipo)
Para asegurarnos el control creamos un método "agregarPlato", solo se debería poder agregar platos a la selección por este método (tristemente python no permite restringirlo verdaderamente)
class Seleccion(models.Model):
platos = models.ManyToManyField(Plato, related_name="selecciones")
comenzal = ....
otros atributos...
def agregarPlato(self, plato):
"""
Controlar aqui regla de que solo
un plato de cada tipo!
"""
pass
La consola
Para abrir la consola de python en eclipse hacer lo siguiente:
Boton derecho en raiz del proyecto->Django->Shell with django environment
El resultado deberia ser el siguiente,,,
El proceso de prueba
Importaciones
Ahora bien, vamos a codificar y probar. Lo primero es importar nuestras clases.
Tip: No es necesario realizar el proceso de importación manualmente, la ide puede ayudar. Simplemente tratemos de instanciar un objeto y con ctrl-space podemos tocar en las sugerencias de importación como indica la imagen
esta técnica puede ahorrar mucho tiempo...
Datos maestros
Volviendo a nuestro tema, vamos a investigar un poco si tenemos los datos que nos permitan realizar la prueba....
plts = Plato.objects.all()
plts
[<Plato: Flan Casero>, <Plato: Omelette>, <Plato: Milanesa de soja>, <Plato: Tortilla>]
Tenemos platos, veamos los tipos de esos platos...
for p in plts:
print(p.tipo.descripcion)
print(p.tipo.descripcion)
Postre
Principal
Principal
Principal
Principal
Principal
Principal
Como vemos los ultimo tres platos son del tipo "Principal" si intento meter mas de uno en una "Seleccion" la clase no debería permitirlo
La prueba
Primero creamos una Seleccion:
from djSisitia.models.Seleccion import Seleccion
sel = Seleccion()
Como la relación es many to many tengo que salvar primero (aun no tengo estudiado el tema).
#Completar todos los datos obligatorios y guardar
sel.save()
Ahora dejamos la consola como esta e intentamos codificar el método "agregarPlato"
Para lograr el objetivo vamos a aplicar una logica muy simple, si ya existe un plato del mismo tipo lanzamos un excepción...
Como estamos aprendiendo a desarrollar en django vamos a usar la consola para investigar como seria preguntar si la selección tiene ya un plato de un tipo determinado, primero metemos platos por izquierda, utilizando el add de la coleccion
plts
[<Plato: Flan Casero>, <Plato: Omelette>, <Plato: Milanesa de soja>, <Plato: Tortilla>]
#Agrego un postre
sel.platos.add(plts[0])
#Pregunto si en la lista de platos de la seleccion existe un plato del tipo plts[0].tipo (que es postre)
sel.platos.filter(tipo=plts[0].tipo)
[<Plato: Flan Casero>]
Listo! Funciona, ahora si a implementar...
def agregarPlato(self, plato):
pl = self.platos.filter(tipo=plato.tipo)
if not pl:
self.platos.add(plato)
else:
raise Exception("Se esta intentando meter mas de plato del mismo tipo")
return self.platos.all().count()
probemos....
sel.agregarPlato(plts[0]) #Se agrega un plato del tipo postre
1 #Exito
sel.agregarPlato(plts[0]) #Se otro plato del tipo postre
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Users\pabli\git\djSisitia\djSisitia\djSisitia\models\Seleccion.py", line 29, in agregarPlato
raise Exception("Se esta intentando meter mas de plato del mismo tipo")
Exception: Se esta intentando meter mas de plato del mismo tipo #Error
sel.agregarPlato(plts[1]) #Se agrega un plato del tipo principal
2 #Exito
sel.agregarPlato(plts[1]) #Se otro plato del tipo principal
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Users\pabli\git\djSisitia\djSisitia\djSisitia\models\Seleccion.py", line 29, in agregarPlato
raise Exception("Se esta intentando meter mas de plato del mismo tipo")
Exception: Se esta intentando meter mas de plato del mismo tipo #Error
Conclusion
Lo mas importante a destacar es que al estar limitados con las capacidades del ide para autocompletar código y especialmente cuando uno esta en la etapa de aprendizaje esta técnica realmente ayuda a probar características, métodos, soluciones. En el ejemplo queda especialmente visible cuando se debió probar las técnicas del filtrado que (aunque son muy básicas) quien esta aprendiendo no domina totalmente.
Tip: Se debe tener en cuenta que ciertos cambios en el código requieren volver a lanzar la consola para que el interprete vuelta a interpretar las implementaciones, desconozco si existe una forma de deshabilitar esto y que reinterprete cualquier cambio, es un tema que voy a investigar y puede ser la próxima entrada dado que me parece que es muy factible que exista.
No hay comentarios:
Publicar un comentario