Google App Engine for Python: probando webapp2

Posted by in Frameworks, Python

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:

Sesiones en GAE

Sesiones en GAE

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:

Probando GAE

Probando GAE

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:

Probando GAE con Python

Probando GAE con Python

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:

Probando GAE

Probando GAE

Espero que os sirva, y os animeis a usar Google App Engine!!

Google+ Comments - Comentarios Google+