De nuevo retomamos un tema en #manejandodatos al que dedicamos mucha teoría y poca práctica. Se trata de trabajar en Google App Engine for Python, a partir del ejemplo explicado aquí: http://www.manejandodatos.es/2014/12/google-app-engine-para-python/. En anteriores entradas se explicó cómo instalar el correspondiente SDK, e incluso os conté cómo hacer una prueba con el framework webapp2, que permite programar para Web con Python. Hoy damos un paso más en el uso de este framework bajo la nube de Google.
Qué es webapp2
Pues … un framework que facilita la realización de tareas. Básicamente, el framework dispone de métodos y propiedades que nos permite concentrarnos en la interfaz de la aplicación y en la gestión, pues del resto se encarga en framework. En concreto, webapp2 es una actualización de webapp, otro framework y que es la base, aunque mejorado. Entre las novedades incluye soporte para enrutado, manejo de sesiones y localización.
Validando la información
A pesar de que el ejemplo que vimos permitía rellenar un formulario y mostrar un saludo, ahora vamos a ampliar dicho código para validar la informción que se recibe. Así, en lugar de mostrar No has puesto nombre, volvemos al formulario inicial si el nombre no contiene al menos 2 letras. La redirección se realiza con self.redirect(“/”), donde apuntamos al directorio raiz.
El problema que supone esta redirección es, en el caso de formularios algo más complejos, la pérdida de la información realizada por dicho usuario, por lo que para mejorar la experiencia deberiamos de ser capaces de almacenar esa información. Nada mejor que usar sesiones!
Sesiones en GAE
Por tanto, lo mejor es usar una sesión. Esto requiere de código adicional que encontramos en gae-sessions, una librería de GAE que facilita esta tarea. Cómo podeis leer en su documentación, es muy ligera, fácil de usar, y tan solo tiene la limitación de 1 Mb de tamaño por sesión (que yo creo que es bastante, para ser una aplicación web almacenando datos!).
Descargamos el fichero y copiamos el directorio gaesessions a donde tenemos la aplicación:
Para utilizar esta librería, debemos realizar un fichero de configuración y que se llamara appengine_config.py, y lo configuramos tal que así:
from gaesessions import SessionsMiddleware from gaesessions import def webapp_add_wagi_middleware(app): app = SessionsMiddleware(app, cookie_key="qwertywewaawasdpdfsdfkllddlkeerrer") return app
La clave de la cookie cookie_key es el que tu quieras, siempre que tenga más de 32 caracteres.
Volvemos al código principal y tenemos que importar get_current_session de gaesession (la que se encarga del trabajo sucio de guardar la información).
Jugando con los valores
Primero vamos a guardar información en la sesion, para ello, cuando pasamos por el método post, recuperamos la información y la almacenamos dentro de la sesión. Además, requeriremos que el nombre tenga al menos 5 caracteres, y en caso contrario, nos ofrecerá un mensaje:
def post(self): session = get_current_session() count = session[self.contador] nombre = self.request.get("nombre") # Guardo la info en Sesion session[self.nombre] = nombre session[self.mens] = '' if len(nombre) < 5: session[self.mens] = 'Nombre demasiado corto!' self.redirect(root) mensaje = ('Hola ... %s, Has entrado %d veces' % (nombre, count)) self.response.out.write(mensaje) session[self.contador] = 0
Para usar esa información, lo haremos desde el get, de igual forma:
def get(self): session = get_current_session() nombre = session.get(self.nombre, '') count = session.get(self.contador) + 1 session[self.contador] = count self.response.write(html % (count, nombre))
Y funciona correctamte:
Sin embargo, un detalle a tener en cuenta es que al trabajar con cadenas, un usuario puede insertar el código necesario para cerrar el HTML, y entonces aparecen cosas extrañas: introducimos m”> a, que equivale a cerrar la cadena y el control, y aparece algo que no debiera cuando se recarga la página:
El problema de esto es que en lugar de código, alguien con no buenas intenciones inyecte código malicioso en Javascript, por ejemplo, así que hay que incluir cgi.escape al recuperar las variables. El código final es:
#!/usr/bin/env python # Manejandodatos.es # Probando Google App Engine con Python # import webapp2 from gaesessions import get_current_session import cgi root = '/' html = """ <html lang="es"> <head><title>Probando Google App Engine for Python</title></head> <body> <h1>Probando Google App Engine for Python</h1> <p>Cargado %d veces</p> <p style="color: red">%s</p> <form method="post"> <label for="nombre">Nombre</label> <input name="nombre" id="nombre" type="text" value="%s" /> <input type="submit" value="Enviar"> </form> </body> </html> """ class MainHandler(webapp2.RequestHandler): contador = 'count' nombre = 'nombre' mens = 'mensaje' def post(self): session = get_current_session() count = session[self.contador] nombre = self.request.get("nombre") # Guardo la info en Sesion session[self.nombre] = nombre if len(nombre) < 5: session[self.mens] = 'Nombre demasiado corto!' self.redirect(root) mensaje = ('Hola ... %s, Has entrado %d veces' % (nombre, count)) self.response.out.write(mensaje) session[self.contador] = 0 def get(self): session = get_current_session() nombre = cgi.escape(session.get(self.nombre, ''), quote=True) count = session.get(self.contador, 0) + 1 # El contador es INTERNO y no necesita control de ESCAPE session[self.contador] = count mensaje = cgi.escape(session.get(self.mens, ''), quote=True) self.response.write(html % (count, mensaje, nombre)) app = webapp2.WSGIApplication([(root, MainHandler)], debug=True)
Y al recargar, comprobamos que ya no tenemos ese problema:
Espero que os sirva, y os animeis a usar Google App Engine!!