Chapter 1: Introducción
Introducción
web2py[web2py] es un marco de código abierto para el desarrollo ágil de aplicaciones web seguras conectadas a servicios de bases de datos; está programado en Python[python] y es programable en Python. web2py es un marco de desarrollo completamente integrado, es decir, contiene todos los componentes que necesitas para armar aplicaciones web totalmente funcionales.
web2py se ha diseñado para guiar al desarrollador web para que siga buenas prácticas en ingeniería de software, como por ejemplo el uso del patrón Modelo Vista Controlador (MVC). web2py separa la representación de los datos (el modelo) de la presentación de los datos (la vista) y de los algoritmos y flujo de operación (el controlador). web2py provee de librerías que ayudan al desarrollador en el diseño, implementación y realización de pruebas, y las administra de forma que las distintas librerías trabajen en conjunto.
web2py se ha construido tomando como base la seguridad. Esto significa que automáticamente resuelve muchos de los problemas que pueden generar vulnerabilidades de seguridad, siguiendo prácticas recomendadas por fuentes autorizadas. Por ejemplo, web2py valida todo dato ingresado (para prevenir la inyección de código fuente), escapa toda salida (para prevenir las Secuencias de comandos en sitios cruzados o cross-site scripting), cambia los nombres de archivos subidos (para evitar el ataque de tipo directory traversal o ataque punto punto barra). web2py se encarga de los problemas de seguridad más importantes, para que los desarrolladores tengan pocas oportunidades de introducir vulnerabilidades.
web2py incluye una Capa de Abstracción de la Base de Datos (DAL) que escribe SQL[sql-w] en forma dinámica para que tu, el desarrollador, no tengas que hacerlo. La DAL sabe cómo generar el SQL en forma transparente para SQLite[sqlite], MySQL[mysql], PostgreSQL[postgres], MSSQL[mssql], FireBird[firebird], Oracle[oracle], IBM DB2[db2], Informix[informix] e Ingres[ingresdb].
La DAL además puede generar llamadas a funciones para el Google Datastore cuando se corre sobre el Google App Engine (GAE)[gae]. Experimentalmente, se soportan más bases de datos y se agregan nuevas constantemente. Si necesitas un adaptador para otra base de datos no listada, puedes buscar información sobre nuevos adaptadores en el sitio de web2py o en la lista de correo. Una vez que una o más tablas de la base de datos se han definido, web2py genera en forma automática una interfaz administrativa para la base de datos completamente funcional con la que se pueden consultar los datos almacenados.
web2py difiere de otros marcos de desarrollo en que es el único marco que adopta el paradigma Web 2.0 en forma total, según el cual la web es la computadora. De hecho, web2py no requiere configuración o instalación alguna; puede correr en cualquier arquitectura que incluya Python (Windows, Windows CE, Mac OS X, iOS, y Unix/Linux), y las fases de desarrollo, despliegue y mantenimiento de la aplicación se pueden realizar por medio de una interfaz web en forma remota o local. web2py corre con CPython (la implementación en C) y PyPy (Python escrito en Python), para las versiones de Python 2.5, 2.6 y 2.7.
web2py provee de un sistema de ticket para reporte de errores. Si ocurre un error, se envía un ticket al usuario, y se registra el error en un log para el administrador.
web2py es código abierto liberado bajo los términos de la licencia LGPL versión 3.
Otra característica importante de web2py es que nosotros, sus desarrolladores, nos hemos propuesto mantener la compatibilidad hacia atrás en versiones futuras. Asó lo hemos hecho desde la primera versión liberada de web2py en octubre del 2007. Se han agregado nuevas características y reparación de fallas, pero si un programa funcionaba con web2py 1.0, ese programa también funcionará del mismo modo actualmente, o incluso mejor.
Estos son algunos ejemplos de instrucciones de web2py que ilustran su potencia y simplicidad. El siguiente código:
db.define_table('persona', Field('nombre'), Field('imagen', 'upload'))
crea una tabla de la base de datos llamada "persona" que tiene dos campos: "nombre", una cadena; e "imagen", algo que debe ser subido (la imagen en sí). Si la tabla ya existe pero no coincide con la definición, se alterará según sea necesario.
Dada la tabla definida más arriba, el siguiente código:
formulario = SQLFORM(db.persona).process()
crea un formulario de ingreso para esa tabla que permite a los usuarios subir imágenes. Además realiza la validación de los formularios enviados, cambia el nombre de la imagen subida en forma segura, almacena la imagen en un archivo, inserta el registro correspondiente en la base de datos, previene el envío duplicado del formulario, y eventualmente modifica el formulario mismo agregando mensajes de error si los datos enviados por el usuario no pasaron la validación.
Este código embebe una wiki completa y lista para usar con etiquetas, la correspondiente nube de etiquetas, incrustar distintos tipos de recursos y soporte para oembed:
def index(): return auth.wiki()
Por otra parte, el siguiente código:
@auth.requires_permission('read', 'persona')
def f(): ....
evita los visitantes accedan a la función f
, a menos que el visitante sea miembro del grupo cuyos miembros tienen permiso para leer ("read") registros de la tabla "persona". Si el visitante no se ha autenticado, se lo redirige a la página de acceso (provista por defecto por web2py).
Además web2py tiene soporte para componentes, es decir, acciones que se pueden incorporar en una vista para que interactúen con el visitante a través de Ajax sin tener que refrescar toda la página. Esto se hace por medio de un ayudante LOAD
que permite un diseño de aplicaciones verdaderamente modular; esto se trata en el capítulo 3 en relación con wiki y con cierto detalle en el último capítulo del libro.
Esta 5.ª edición del libro cubre web2py
2.4.1 y versiones posteriores.
Principios
La programación en Python sigue típicamente estos principios básicos:
- No te repitas (DRY).
- Debería haber una única forma para hacer las cosas.
- Explícito es mejor que implícito.
web2py respeta estrictamente los dos primeros principios obligando al desarrollador a que use prácticas reconocidas de ingeniería de software que desalientan la repetición de código fuente. web2py guía al desarrollador a través de casi todas las tareas comunes en el desarrollo de aplicaciones web (creación y procesamiento de formularios, administración de sesiones, cookie, errores, etc.).
web2py se diferencia de otros marcos de desarrollo en relación con el tercer principio, que a veces entra en conflicto con los otros dos. En especial, web2py no importa las aplicaciones de usuarios, sino que las ejecuta en un contexto predefinido. Este contexto expone las palabras clave de Python (Python keywords) así como también las palabras clave de web2py.
Para algunos esto puede parecer magia, pero no debería ser así. Simplemente, en realidad, algunos módulos ya se han importado sin que tu debas hacerlo. web2py intenta eludir la molesta característica de otros marcos de desarrollo que obligan al desarrollador a que importe los mismos módulos al inicio de cada modelo y de cada controlador.
Al importar sus propios módulos, web2py ahorra tiempo y evita errores y confusiones, siguiendo de esa forma el espíritu de no repetirse y también de la unicidad del método para una tarea específica.
Si el desarrollador quiere usar otros módulos de Python o módulos de terceros, esos módulos se deben importar en forma explícita, como con cualquier otro programa en Python.
Marcos de Desarrollo Web
En su nivel más elemental, una aplicación web consiste de un conjunto de programas (o funciones) que se ejecutan cuando se visita un determinado URL. La salida del programa se devuelve al visitante y es procesada por el navegador.
El propósito de los marcos de desarrollo web es el de permitir a los desarrolladores la creación de nuevas aplicaciones con rapidez, facilidad y sin cometer errores. Esto se logra presentando interfaces API y herramientas que reducen y simplifican la cantidad de código que se requiere.
Los dos métodos clásicos para el desarrollo de aplicaciones web son:
- Generar HTML[html-w] [html-o] al vuelo, en forma programática.
- Embeber código fuente en páginas HTML.
La primera técnica es la que se ha utilizado, por ejemplo, en los primeros script CGI. El segundo modelo de trabajo es el que se usa para PHP[php] (donde el código está escrito en PHP, un lenguaje parecido a C), ASP (con código Visual Basic), y JSP (que utiliza Java).
Aquí se puede ver un ejemplo de programa en PHP que, cuando se ejecuta, recupera información de una base de datos y devuelve una página HTML que muestra los registros recuperados:
<html><body><h1>Registros</h1><?
mysql_connect(localhost, usuario, clave);
@mysql_select_db(database) or die( "Imposible recuperar datos");
$consulta="SELECT * FROM contactos";
$resultado=mysql_query($consulta);
mysql_close();
$i=0;
while ($i < mysql_numrows($resultado)) {
$nombre=mysql_result($resultado, $i, "nombre");
$telefono=mysql_result($resultado, $i, "telefono");
echo "<b>$nombre</b><br>Teléfono:$telefono<br /><br /><hr /><br />";
$i++;
}
?></body></html>
El problema con este tipo de solución es que el código está incrustado en el HTML, pero ese mismo código también debe generar HTML adicional y además generar las instrucciones SQL para consultar la base de datos, enredando múltiples capas de la aplicación y haciendo que el código sea de difícil lectura y mantenimiento. La situación es aún peor para el caso de aplicaciones que usan Ajax, y la complejidad crece con el número de páginas (archivos) que componen la aplicación.
La funcionalidad implementada por el código arriba se puede expresar en web2py con dos líneas de código en Python:
def index():
return HTML(BODY(H1('Registros'), db().select(db.contactos.ALL)))
En este simple ejemplo, la estructura de la página HTML es representada en forma programática por los objetos HTML
, BODY
, Y H1
; la base de datos db
se consulta con el comando select
; por último, todo se serializa como HTML. Observa que db
no es una palabra especial sino una variable definida por el usuario. Usaremos este nombre como una convención para referirnos en general a una conexión de la base de datos.
Los marcos de desarrollo web se suelen separar en dos categorías: Un marco de desarrollo glued (pegado) se arma ensamblando (pegando juntos) muchos componentes de terceros. Un marco de desarrollo full-stack (completo e integrado) se arma creando componentes especialmente diseñados para estar fuertemente ligados y trabajar en conjunto.
web2py es un marco de desarrollo full-stack. Prácticamente todos sus elementos se han creado desde cero y se diseñaron para funcionar en conjunto, pero además están preparados para funcionar en forma independientemente, como componentes de terceros de otras aplicaciones. Por ejemplo, la Capa de Abstracción de la Base de Datos (DAL) o el lenguaje de plantillas se pueden usar en forma independiente de web2py, importando gluon.dal
o gluon.template
en tus propias aplicaciones. gluon
es el nombre del paquete que contiene las librerías del sistema. Algunas librerías de web2py, como las que crean y procesan formularios a partir de tablas de bases de datos, tienen como dependencias otras partes de web2py. Además, web2py puede funcionar con librerías Python de terceros, incluyendo otros lenguajes de plantillas y capas de abstracción de bases de datos, pero estas librerías no se integrarán en el mismo grado que los componentes originales.
Modelo-Vista-Controlador
web2py alienta al desarrollador a que separe la representación de los datos (el modelo), la presentación de los datos (la vista) y el flujo de operación o workflow de la aplicación (el del controlador). Consideremos nuevamente el ejemplo anterior y veamos cómo podemos crear una aplicación en torno de él. Este es un ejemplo de la interfaz de edición MVC:
El típico flujo de trabajo de una solicitud en web2py se describe en el siguiente diagrama:
En el diagrama:
- El servidor puede ser el o bien el servidor incorporado o un servidor de terceros, como por ejemplo Apache. El servidor maneja múltiples hilos (tiene soporte para multi-threading).
- "main" es la aplicación principal WSGI. Realiza todas las tareas comunes y envuelve la aplicación del usuario. Se encarga del manejo de las cookie, sesiones, transacciones, enrutamiento de URL y enrutamiento inverso, y la administración de direcciones o dispatching. Puede administrar y realizar transmisiones de archivos estáticos si el servidor web no se ha configurado para hacerlo.
- Los componentes de los Modelos, las Vistas y los Controladores, conforman la aplicación del usuario.
- Se pueden alojar múltiples aplicaciones en la misma instancia de web2py.
- Las flechas suaves representan la comunicación con el motor de la base de datos (o los motores). Las consultas a la base de datos se pueden escribir en SQL puro (no está recomendado) o usando la Capa de Abstracción de la Base de Datos (la forma recomendada), de manera que el código de las aplicaciones no depende de una base de datos específica.
- El administrador de direcciones asocia la URL solicitada a una llamada a función en el controlador. La salida de la función puede ser una cadena o un diccionario conteniendo pares nombre-valor (una hash table). Los datos contenidos en el diccionario se convierten en la página HTML. Si el visitante solicita la misma página en XML, web2py busca una vista que pueda convertir el diccionario a XML. El desarrollador puede crear vistas que conviertan páginas en cualquier protocolo soportado (HTML, XML, JSON, RSS, CSV y RTF) o en protocolos personalizados adicionales.
- Todas las llamadas se envuelven en una transacción, y toda excepción no manejada hace que la transacción recupere el estado inicial. Si la solicitud tiene éxito, se aplican los cambios a la base de datos.
- web2py además maneja sesiones y los cookie de sesión en forma automática, y cuando se aplican los cambios de una transacción, también se almacena la sesión, a menos que se especifique lo contrario.
- Es posible registrar tareas recurrentes (por medio de cron) para que se ejecuten según un programa en un momento determinado y/o al finalizar ciertas acciones. De esta forma es posible correr tareas largas y que requieren un uso intensivo del hardware en segundo plano sin que la navegación se torne más lenta.
He aquí una aplicación mínima pero completa MVC, que consiste en tres archivos:
"db.py" es el modelo:
db = DAL('sqlite://storage.sqlite')
db.define_table('contacto',
Field('nombre'),
Field('telefono'))
Este código conecta a la base de datos (para este ejemplo una base de datos SQLite almacenada en el archivo storage.sqlite
) y define una tabla llamada contacto
. Si la tabla no existe, web2py la crea y, en forma transparente, genera el código SQL en el dialecto apropiado para el motor de la base de datos específico que usa.
El desarrollador puede ver el SQL generado, pero no necesita modificarlo cuando la base de datos, que por defecto es SQLite, se reemplaza por MySQL, PostgreSQL, MSSQL, FireBird, Oracle, DB2, Informix, Interbase, Ingres, o Google App Engine (tanto para SQL como para NoSQL).
Una vez que se ha definido y creado una tabla, web2py además genera una interfaz de administración de la base de datos completamente funcional, llamada appadmin, para poder acceder a esa base de datos y a sus tablas.
"default.py" es el controlador:
def contactos():
grid=SQLFORM.grid(db.contacto, user_signature=False)
return locals()
En web2py, los URL se asocian a módulos de Python y llamadas a funciones. En este caso, el controlador contiene una única función o "acción" llamada contactos
. Toda acción puede devolver una cadena (la página web devuelta) o un diccionario de Python (un conjunto de pares clave:valor
) o un conjunto de las variables locales (como en este ejemplo). Si la función devuelve un diccionario, se pasa a la vista con el mismo nombre que el controlador y la función, que a su vez convierte (render) la página. En este ejemplo, la función contactos
genera una grilla que incluye los comandos recuperar/buscar/crear/modificar/borrar para la tabla db.contacto
y devuelve la grilla a la vista.
"default/contactos.html" es la vista:
{{extend 'layout.html'}}
<h1>Administración de contactos</h1>
{{=grid}}
Esta vista es llamada automáticamente por web2py luego de que la función del controlador asociado (acción) se ejecute. La tarea de esta vista es la conversión de las variables en el diccionario devuelto (para este caso grid
) en HTML. El archivo de la vista está escrito en HTML, pero embebe código de Python delimitado por los signos especiales {{
y }}
. Esto es bastante distinto al ejemplo de código fuente de PHP, porque el único código embebido en el HTML es código de la "capa de presentación". El archivo "layout.html" al que se hace referencia en la parte superior de la vista es provisto por web2py constituye el diseño de página básico para toda aplicación de web2py. El archivo del diseño de página se puede reemplazar o modificar fácilmente.
¿Por qué web2py?
web2py es uno entre los varios marcos de aplicaciones web, pero tiene algunas características atractivas que lo diferencian.
web2py se desarrolló inicialmente como una herramienta para enseñanza, con las siguientes motivaciones básicas:
- Que fuera fácil para los usuarios aprender desarrollo web del lado del servidor sin comprometer la funcionalidad. Por esa razón, web2py no requiere instalación ni configuración, no tiene dependencias (excepto la distribución de código fuente, que requiere Python 2.5 y los módulos de las librerías estándar), y expone la mayor parte de su funcionalidad a través de una interfaz de navegador web, incluyendo un entorno integrado de desarrollo con un depurador y una interfaz para la base de datos.
- web2py se ha mantenido estable desde el primer día porque sigue un diseño
top-down
; por ejemplo, su API fue diseñada antes de ser implementada. Incluso si bien nuevas funcionalidades fueron agregadas, web2py nunca ha introducido incompatibilidades hacia atrás, y no va a introducir incompatibilidades cuando se agreguen nuevas características en el futuro. - web2py resuelve activamente los problemas de seguridad más importantes que plagan a muchas aplicaciones web modernas, según el análisis de OWASP[owasp] que se puede consultar más abajo.
- web2py es liviano. Su núcleo de librerías, incluyendo la Capa de Abstracción de la Base de Datos, el lenguaje de plantillas, y el conjunto completo de ayudantes pesan 1.4MB. El código fuente completo incluyendo aplicaciones de ejemplo e imágenes pesa 10.4MB.
- web2py tiene una huella (footprint) pequeña y es realmente rápido. Utiliza el servidor WSGI Rocket [rocket] desarrollado por Timothy Farrell. Es tan rápido como Apache con mod_wsgi, y además tiene soporte para SSL e IPv6.
- web2py usa sintaxis Python para modelos, controladores y vistas, pero no importa modelos y controladores (a diferencia del resto de los marcos de desarrollo) - sino que los ejecuta. Esto significa que las app pueden instalarse, desinstalarse y modificarse sin tener que reiniciar el servidor web (incluso en producción), y aplicaciones diferentes pueden coexistir sin que sus módulos interfieran entre sí.
- web2py utiliza una Capa de Abstracción de la Base de Datos (DAL) en lugar del mapeo objeto-relacional (ORM). Desde un punto de vista conceptual, esto significa que distintas tablas de bases de datos se asocian (
map
) en diferentes instancias de una claseTable
y no en distintas clases, mientras que los registros se asocian o mapean a instancias de una claseRow
, no a instancias de la clase de la tabla correspondiente. Desde un punto de vista práctico, significa que la sintaxis SQL se asocia en una relación uno a uno en la sintaxis de DAL, y no es necesaria una "caja negra" con programación compleja de metaclases como es común en los ORM más populares, que implicaría un incremento de la latencia.
WSGI [wsgi-w,wsgi-o] (Web Server Gateway Interface) es un estándar moderno de Python para comunicaciones entre un servidor web y aplicaciones Python.
Aquí se puede ver una captura de la interfaz administrativa de web2py admin:
Seguridad
El Open Web Application Security Project[owasp] (OWASP) es una libre y abierta dedicada a mejorar la seguridad para aplicaciones de software.
OWASP ha listado los mayores problemas de seguridad que pueden poner en peligro a las aplicaciones web. Esa lista se reproduce a continuación, junto con una descripción de cómo se resuelve cada uno de los problemas en web2py:
- cross site scriptingCross Site Scripting (XSS): las vulnerabilidades de Secuencias de comandos en sitios cruzados ocurren cuando una aplicación toma datos provistos por el usuario y los envía a un navegador web sin previamente validar o codificar el contenido. XSS permite a los atacantes ejecutar script en el navegador de la víctima que pueden tomar control de la sesión del usuario, desfigurar sitios web, probablemente introducir "gusanos", etc. web2py, por defecto, "escapa" todas las variables procesadas en la vista, previniendo el XSS.
- injection flawsInjection Flaws (vulnerabilidades de inyección de código fuente): La inyección, en particular la de SQL, es común en las aplicaciones web. Las inyecciones ocurren cuando información provista por el usuario es enviada como parte de una instrucción o consulta. La información hostil del atacante engaña al intérprete para que ejecute comandos no esperados o para que modifique información. web2py incluye una Capa de Abstracción de la Base de Datos que hace imposible la inyección de SQL. Normalmente, las instrucciones SQL no son escritas por el desarrollador. En cambio, el SQL es generado dinámicamente por el DAL, asegurando que toda información ingresada se haya escapado correctamente.
- malicious file executionMalicious File Execution (ejecución maliciosa de archivos): El código vulnerable a la inclusión remota de archivos (RFI) permite a los atacantes incluir código hostil e información, dando como resultado ataques devastadores, como por ejemplo el compromiso total del servidor. web2py permite únicamente la ejecución de funciones expuestas, previniendo la ejecución maliciosa de archivos. Las funciones importadas nunca se exponen; sólo se exponen las acciones. web2py utiliza una interfaz administrativa web que hace muy fácil el seguimiento de las acciones que se han expuesto.
- insecure object referenceInsecure Direct Object Reference (referencias directas a objetos inseguros): una referencia directa a un objeto ocurre cuando un desarrollador expone una referencia a un objeto de implementación interna, como un archivo, directorio, registro de la base de datos o clave, como URL o parámetro de formulario. Los atacantes pueden manipular esas referencias para acceder a otros objetos sin autorización. web2py no expone ningún objeto interno; es más, web2py valida toda URL, previniendo de esa forma los denominados ataques de tipo
directory traversal
. web2py también provee un mecanismo simple para la creación de formularios que automáticamente valida todas los datos ingresados. - CSRFCross Site Request Forgery (CSRF) o Suplantación de identidad entre servidores: Un ataque CSRF fuerza al navegador de una víctima autenticada a que envíe una solicitud preautenticada a una aplicación web vulnerable, que entonces fuerza al navegador de la víctima a realizar una acción hostil en beneficio del atacante. El CSFR puede ser tan grave como la importancia de la aplicación web a la que ataca. web2py previene el CSRF tanto como los envíos de formularios duplicadas por error asignando una clave única aleatoria a cada formulario. Incluso, web2py utiliza UUID para la cookie de la sesión.
- information leakageimproper error handlingInformation Leakage and Improper Error Handling (Filtrado de información y manejo inapropiado de errores): Las aplicaciones pueden filtrar inadvertidamente información sobre su configuración, constitución interna, o violar la privacidad a través de una serie de problemas en la aplicación misma. Los atacantes utilizan estas debilidades para hurtar información sensible, o perpetrar ataques más peligrosos. web2py incluye un sistema de ticket de reporte. Ningún error puede resultar en código expuesto al usuario. Todos los errores se almacenan y se envía el ticket al usuario para permitir su seguimiento. Pero el detalle de los errores sólo es accesible para el administrador.
- Broken Authentication and Session Management (Fallos de autenticación y manejo de sesiones): Las credenciales y claves de sesión a menudo no se protegen apropiadamente. Los atacantes pueden acceder a contraseñas, claves o referencias cifradas para falsificar la identidad del usuario (por ejemplo autenticándose como un usuario registrado). web2py incorpora un mecanismo para autenticación administrativa, y maneja las sesiones en forma independiente para cada aplicación. La interfaz administrativa además fuerza el uso de cookie seguras cuando el cliente no está en "localhost". Para las aplicaciones, incluye una poderosa API para Control de Acceso Basada en Roles (
RBAC
) - cryptographic storeInsecure Cryptographic Storage (Almacenamiento criptográfico inseguro): Las aplicaciones web raramente utilizan funciones criptográficas apropiadamente para proteger datos y credenciales. Los atacantes utilizan la información débilmente protegida para el robo de identidad y otros crímenes, como el fraude con tarjetas de crédito. web2py usa los algoritmos MD5 o el HMAC+SHA-512 para proteger las contraseñas almacenadas. Existen otros algoritmos también disponibles.
- secure communicationsInsecure Communications (inseguridad de transferencias): Las aplicaciones frecuentemente omiten la encripción del tráfico de red cuando es necesario para proteger comunicaciones sensibles. web2py incluye el [ssl] servidor Rocket WSGI con soporte para SSL, pero también puede utilizar Apache o Lighthttpd y mod_ssl para servir comunicaciones con cifrado SSL.
- access restrictionFailure to Restrict URL Access (Acceso irrestricto con URL): Con frecuencia una aplicación sólo protege las funcionalidades sensibles evitando mostrar link o direcciones URL a usuarios no autorizados. Los atacantes pueden utilizar esta debilidad para acceder y realizar operaciones no autorizadas accediendo a esos URL directamente. web2py asocia las solicitudes URL a módulos y funciones de Python. web2py provee de un mecanismo para declarar cuáles funciones son públicas y cuáles requieren autenticación y autorización. La API de Control de Acceso Basado en Roles incorporada permite a los desarrolladores la restricción de acceso a cualquier función basada en autenticación simple (
login
), pertenencia a grupo o permisos basados en grupos. La permisología es minuciosa y se puede combinar con filtros de la base de datos para permitir, por ejemplo, el acceso a un conjunto específico de tablas y/o registros. web2py además permite el uso de direcciones URL con firma digital y provee de una API para firmar digitalmente solicitudes con ajax.
Las características de web2py se han analizado en función de su seguridad y los resultados se pueden consultar en ref.[pythonsecurity].
El paquete y su contenido
Puedes descargar web2py desde el sitio oficial:
http://www.web2py.com
web2py está compuesto por los siguientes componentes:
- librerías: proveen de las funcionalidades del núcleo de web2py y se puede acceder a ellas en forma programática.
- servidor web: el servidor web WSGI Rocket.
- la aplicación admin: se usa para crear, diseñar y administrar las demás aplicaciones. admin provee de un completo Entorno de Integrado de Desarrollo (IDE) para la creación de aplicaciones web2py. Además incluye otras funcionalidades, como el entorno de pruebas para interfaz web y la consola shell para navegador.
- la aplicación examples: contiene documentación y ejemplos interactivos. examples es un clon del sitio web oficial, e incluye la documentación epydoc.
- la aplicación welcome: la plantilla de andamiaje para cualquier otra aplicación. Por defecto, incluye un menú desplegable escalonado CSS y un sistema de autenticación (que se detalla en el Capítulo 9).
web2py se distribuye como código fuente, y en formato binario para Microsoft Windows y para Mac OS X.
La distribución de código fuente se puede usar en cualquier plataforma que corra Python e incluye los componentes mencionados más arriba. Para correr el código fuente, necesitas tener instalado previamente Python 2.5 o 2.7 en el sistema. Además necesitas alguno de los motores de bases de datos soportados instalado. Para pruebas y aplicaciones de baja demanda, puedes usar la base de datos SQLite, que se incluye en las instalaciones de Python 2.7.
Las versiones binarias de web2py (para Windows y Mac OS X) incluyen un intérprete de Python 2.7 y la base de datos SQLite). Técnicamente hablando, estos no son componentes de web2py. El incluirlos en la distribución binaria te permite utilizar web2py en forma instantánea.
La siguiente imagen ilustra la estructura aproximada de web2py:
En la parte inferior se puede encontrar el intérprete. Si nos desplazamos hacia arriba encontramos el servidor web (rocket), las librerías, y las aplicaciones. Cada aplicación cuenta con su propio diseño MVC (modelos, controladores, vistas, idiomas, bases de datos, y archivos estáticos). Cada aplicación incluye su propia interfaz de administración de la base de datos (appadmin). Cada instancia de web2py incluye por defecto tres aplicaciones: welcome (la app de andamiaje), admin (el IDE para navegador), y examples (la copia del sitio web y los ejemplos).
Acerca de este libro
Este libro incluye los siguientes capítulos, además de su introducción:
- Capítulo 2: es una introducción minimalista a Python. Se supone que el lector conoce tanto los conceptos básicos de programación estructurada como de programación orientada a objetos, como por ejemplo las nociones de bucle, condición, función y clase, y describe la sintaxis básica de Python. Además se agregan ejemplos para módulos de Python que se usan en el resto del libro. Si ya conoces Python, puedes omitir este capítulo.
- Capítulo 3: muestra como se inicia web2py, describe la interfaz administrativa y guía al lector a través de varios ejemplos que van creciendo en complejidad: una aplicación que devuelve una cadena, una aplicación para conteo, un blog de imágenes, una wiki completa y con características avanzadas que permite subir imágenes y hacer comentarios, provee de un servicio de autenticación, autorización, webservices y una fuente RSS. Mientras lees este capítulo, puedes consultar el Capítulo 2 como referencia para la sintaxis general de Python o el resto de los capítulos para una referencia más detallada sobre las características que se usan.
- Capítulo 4: describe en una forma más sistemática la estructura del núcleo y sus librerías: traducción de URL, solicitudes, respuestas, caché, planificador, tareas en segundo plano, traducción automática y el flujo de trabajo general o workflow.
- Capítulo 5: es una guía de referencia para el lenguaje de plantillas usado para la creación de vistas. Muestra cómo embeber código de Python en HTML, e ilustra el uso de los ayudantes (objetos que pueden crear HTML).
- Capítulo 6: describe la Capa de Abtracción de la Base de Datos, o DAL. La sintaxis de DAL se expone por medio de una serie de ejemplos.
- Capítulo 7: describe los formularios, su validación y procesamiento. FORM es el ayudante de bajo nivel para creación de formularios. SQLFORM es el creador de formularios de alto nivel. En el Capítulo 7 además se describe la API para Crear/Leer/Modificar/Borrar (CRUD).
- Capítulo 8: describe las funcionalidades de comunicaciones como el envío de correo y SMS y la lectura de bandejas de correo.
- Capítulo 9: describe la autenticación y autorización y el mecanismo ampliable para Control de Acceso disponible en web2py. Además incluye la configuración de Mail (para correo electrónico) y CAPTCHA, ya que se usan en conjunto con el sistema de autenticación. En la tercera edición del libro hemos agregado un detalle pormenorizado de la integración con sistemas de autenticación de terceros como OpenID, OAuth, Google, Facebook, LinkedIn, etc.
- Capítulo 10: trata sobre la creación de webservices con web2py. Daremos ejemplos de integración con el Google Web Toolkit a través de Pyjamas, y también para Adebe Flash y PyAMF.
- Capítulo 11: incluye recetas para jQuery y web2py. web2py se diseñó principalmene para la programación del lado del servidor, pero incluye jQuery, ya que hemos comprobado que es la mejor librería de JavaScript de código abierto disponible para la creación de efectos y el uso de Ajax. En este capítulo, se describe el uso eficiente de jQuery en combinación con web2py.
- Capítulo 12: describe los componentes y plugin de web2py como herramientas para la creación de aplicaciones modulares. Crearemos un plugin como ejemplo que implementa funcionalidades de uso común, como la generación de gráficas, comentarios y el uso de etiquetas.
- Capítulo 13: trata sobre la implementación en producción de aplicaciones web2py. Se trata en especial sobre la implementación en servidores web LAMP (considerada la alternativa de más peso). Se describen además servicios alternativos y la configuración de la base de datos PostgreSQL. También se detalla cómo correr web2py como un servicio en un entorno Microsoft Windows, y la implementación en algunas plataformas específicas incluyendo Google App Engine, Heroku, y PythonAnywhere. Además, en este capítulo, hablaremos sobre cuestiones de escalabilidad y seguridad.
- Capítulo 14: contiene varias recetas para realizar otras tareas específicas, incluyendo los upgrade (actualizaciones del núcleo), geocoding (aplicaciones geográficas), paginación, la API de Twitter, y más.
Este libro sólo cubre las funcionalidades básicas y la API incorporada de web2py. Por otra parte, este libro no cubre las appliances (es decir, aplicaciones llave en mano).
Puedes descargar esas aplicaciones desde el sitio web [appliances].
Se puede encontrar información complementaria en los hilos del grupo de usuarios[usergroup] (grupo de usuarios de web2py). También está disponible como referencia AlterEgo[alterego], el antiguo blog y listado de preguntas frecuentes de web2py.
Este libro fue escrito utilizando la sintaxis markmin y fue automáticamente convertido a los formatos HTML, LaTex y PDF.
Soporte
El canal principal para obtener soporte es el grupo de usuarios[usergroup], con docenas de publicaciones diarias. Incluso si eres un novato, no dudes en consultar - será un placer ayudarte.
También disponemos de un sistema para el reporte de problemas (issue tracker) en https://github.com/web2py/web2py/issues . Por último pero no menos importante, puedes obtener soporte profesional (consulta la página web para más detalles).
Cómo contribuir
Toda ayuda es realmente apreciada. Puedes ayudar a otros usuarios en el grupo de usuarios, o directamente enviando parches del programa (en el sitio de GitHub https://github.com/web2py/web2py). Incluso si encuentras un error de edición en este libro, o quieres proponer una mejora, la mejor forma de ayudar es haciendo un parche del libro en sí (que está en https://github.com/mdipierro/web2py-book).
Normas de estilo
PEP8 [style] contiene un compendio de buenas prácticas de estilo para programar en Python. Encontrarás que web2py no siempre sigue estas reglas. Esto no se debe a omisiones o negligencia; nosotros creemos que los usuarios de web2py deberían seguir estas reglas y los alentamos a hacerlo. Hemos preferido no seguir algunas de estas reglas cuando definimos objetos ayudantes con el propósito de minimizar la posibilidad de conflictos con los nombres de objetos creados por el usuario.
Por ejemplo, la clase que representa un <div>
se llama DIV
, mientras que según las reglas de estilo de Python se la debería haber llamado Div
. Creemos que, para el ejemplo específico dado, el uso de mayúsculas en toda la palabra "DIV" es una elección más natural. Más aún, esta técnica le da libertad a los programadores para que puedan crear una clase llamada "Div", si así lo quisieran. Nuestra sintaxis además, coincide naturalmente con la notación DOM de la mayoría de los navegadores (incluyendo, por ejemplo, Firefox).
Según la guía de estilo de Pyhton, todas las cadenas mayúsculas se deberían usar para constantes, no para variables. Siguiendo con nuestro ejemplo, incluso considerando que DIV
es una clase, se trata de una clase especial que nunca debería ser modificada por el usuario porque el hacerlo implicaría una incompatibilidad con otras aplicaciones de web2py. Por lo tanto, creemos que esto autoriza el uso de DIV
porque esa clase debería tratarse como constante, justificandose de esta forma la notación elegida.
En resumen, se siguen las siguientes convenciones:
- Los ayudantes HTML se notan con mayúsculas para toda la palabra como se describió anteriormente (por ejemplo
DIV
,A
,FORM
,URL
). - El objeto de traducción
T
se escribe con mayúscula aunque se trate de una instancia de la clase, no la clase en sí. Lógicamente, el objeto traductor realiza una acción similar a la de los ayudantes de HTML; este objeto opera en parte de la conversión (rendering) de la información presentada. Además,T
debe ser fácil de identificar en el código fuente y debe tener un nombre corto. - Las clases de la DAL siguen el estándar de estilo de Python (mayúscula en la primera letra), por ejemplo
Table
,Field
,Query
,Row
,Rows
, etc.
Para el resto de los casos, creemos que hemos seguido en lo posible, la guía de estilo de Python (PEP8). Por ejemplo, todas las instancias de objetos son en minúsculas (request, response, session, cache), y todas las clases internas tienen mayúsculas iniciales.
En todos los ejemplos de este libro, las palabras clave de web2py se muestran en negrita, mientras que las cadenas y comentarios se muestran en letra itálica o inclinada.
Licencia
web2py se distribuye según los términos de la licencia LGPL versión 3. El texto completo de la licencia está disponible en ref.[lgpl3]
En conformidad con LGPL puedes:
- redistribuir web2py con tus aplicaciones (incluyendo las versiones binarias oficiales)
- distribuir tus aplicaciones usando las librerías oficiales de web2py según la licencia que elijas.
Pero tienes la obligación de:
- disponer de las aclaraciones necesarias para dar noticia del uso de web2py en la documentación
- distribuir toda modificación de las librerías de web2py con licencia LGPLv3.
La licencia incluye las aclaraciones y advertencias usuales:
NO HAY GARANTÍAS PARA EL PROGRAMA, EN LA MEDIDA PERMITIDA POR LA LEY APLICABLE. EXCEPTO CUANDO SE INDIQUE LO CONTRARIO POR ESCRITO, LOS TITULARES DEL COPYRIGHT Y/U OTRAS PARTES PROPORCIONAN EL PROGRAMA "TAL CUAL" SIN GARANTÍAS DE NINGÚN TIPO, YA SEAN EXPRESAS O IMPLICADAS, INCLUYENDO, PERO NO LIMITADO A, LAS GARANTÍAS IMPLÍCITAS DE COMERCIALIZACIÓN Y APTITUD PARA UN PROPÓSITO PARTICULAR. EL RIESGO EN CUANTO A LA CALIDAD Y RENDIMIENTO DEL PROGRAMA QUEDA BAJO SU RESPONSABILIDAD. SI EL PROGRAMA ES DEFECTUOSO, USTED ASUME EL COSTO DE TODO SERVICIO, REPARACIÓN O CORRECCIÓN.
EN NINGÚN CASO, A MENOS QUE LO EXIJA LA LEY APLICABLE O QUE SEA ACORDADO POR ESCRITO, UN TITULAR DE DERECHO DE AUTOR O CUALQUIER OTRA PARTE QUE MODIFIQUE Y/O TRANSMITA EL PROGRAMA COMO SE PERMITE ARRIBA, SERÁ RESPONSABLE ANTE USTED POR DAÑOS, INCLUYENDO CUALQUIER DAÑO GENERAL, ESPECIAL, INCIDENTAL O DAÑOS DERIVADOS DEL USO O IMPOSIBILIDAD DE USAR EL PROGRAMA, INCLUYENDO PERO NO LIMITADO A, LA PÉRDIDA O DAÑO DE DATOS, LAS PÉRDIDAS SUFRIDAS POR USTED O TERCEROS O UN FALLO DEL PROGRAMA PARA OPERAR CON CUALQUIER OTRO PROGRAMA, INCLUSO SI EL PROPIETARIO O PARTE DE OTRO TIPO FUE INFORMADA SOBRE LA POSIBILIDAD DE TALES DAÑOS.
Primeras anteriores
Las primeras versiones de web2py, 1.0.*-1.90.*, se publicaron bajo la licencia GPL2 con una cláusula adicional para fines comerciales que, por razones prácticas, era muy similar a la actual licencia LGPLv3.
Software de terceros distribuido en conjunto con web2py
web2py contiene software de terceros en la carpeta gluon/contrib/ y varios archivos de JavaScript y CSS. Estos archivos se distribuyeron con web2py según los términos de sus licencias originales, como se detalla en los respectivos archivos.
Agradecimientos
web2py fue originalmente desarrollado y registrado por Massimo Di Pierro. La primera versión (1.0) se liberó en octubre del año 2007. Desde entonces ha sido adoptado por muchos usuarios, y algunos de ellos también han contribuido con reportes de fallas, pruebas, depuración, parches, y la corrección de este libro.
Algunos de los desarrolladores y colaboradores más importantes son, en orden alfabético, ordenados por el primer nombre:
Adam Bryzak, Adam Gojdas, Adrian Klaver, Alain Boulch, Alan Etkin, Alec Taylor, Alexandre Andrade, Alexey Nezhdanov, Alvaro Justen, Anand Vaidya, Anatoly Belyakov, Ander Arbelaiz, Anders Roos, Andrew Replogle, Andrew Willimott, Angelo Compagnucci, Angelo y Villas, Annet Vermeer, Anthony Bastardi, Anton Muecki, Antonio Ramos, Arun Rajeevan, Attila Csipa, Ben Goosman, Ben Reinhart, Benjamin, Bernd Rothert, Bill Ferret, Blomqvist, Boris Manojlovic, Branko Vukelic, Brent Zeiben, Brian Cottingham, Brian Harrison, Brian Meredyk, Bruno Rocha, CJ Lazell, Caleb Hattingh, Carlos Galindo, Carlos Hanson, Carsten Haese, Cedric Meyer, Charles Law, Charles Winebrinner, Chris Clark, Chris May, Chris Sanders, Christian Foster Howes, Christopher Smiga, Christopher Steel, Clavin Sim, Cliff Kachinske, Corne Dickens, Craig Younkins, Dan McGee, Dan Ragubba, Dane Wright, Danny Morgan, Daniel Gonz, Daniel Haag, Daniel Lin, Dave Stoll, David Adley, David Harrison, David Lin, David Marko, David Wagner, Denes Lengyel, Diaz Luis, Dirk Krause, Dominic Koenig, Doug Warren, Douglas Philips, Douglas Soares de Andrade, Douglas y Alan, Dustin Bensing, Elcio Ferreira, Eric Vicenti, Erwin Olario, Falko Krause, Farsheed Ashouri, Felipe Meirelles, Flavien Scheurer, Fran Boon, Francisco Gama, Fred Yanowski, Friedrich Weber, Gabriele Alberti, Gergely Kontra, Gergely Peli, Gerley Kontra, Gilson Filho, Glenn Caltech, Graham Dumpleton, Gregory Benjamin, Gustavo Di Pietro, Gyuris Szabolcs, Hamdy Abdel-Badeea, Hans C. v. Stockhausen, Hans Donner, Hans Murx, Huaiyu Wang, Ian Reinhart Geiser, Iceberg, Igor Gassko, Ismael Serratos, Jan Beilicke, Jay Kelkar, Jeff Bauer, Jesus Matrinez, Jim Karsten, Joachim Breitsprecher, Joakim Eriksson, Joe Barnhart, Joel Carrier, Joel Samuelsson, John Heenan, Jon Romero, Jonas Rundberg, Jonathan Benn, Jonathan Lundell, Jose Jachuf, Joseph Piron, Josh Goldfoot, Josh Jaques, José Vicente de Sousa, Jurgis Pralgauskis, Keith Yang, Kenji Hosoda, Kenneth Lundstr, Kirill Spitsin, Kyle Smith, Larry Weinberg, Limodou, Loren McGinnis, Louis DaPrato, Luca De Alfaro, Luca Zachetti, Lucas D'Ávila, Madhukar R Pai, Manuele Presenti, Marc Abramowitz, Marcel Hellkamp, Marcel Leuthi, Marcello Della Longa, Margaret Greaney, Maria Mitica, Mariano Reingart, Marin Prajic, Marin Pranji, Marius van Niekerk, Mark Kirkwood, Mark Larsen, Mark Moore, Markus Gritsch, Mart Senecal, Martin Hufsky, Martin Mulone, Martin Weissenboeck, Mateusz Banach, Mathew Grabau, Mathieu Clabaut, Matt Doiron, Matthew Norris, Michael Fig, Michael Herman, Michael Howden, Michael Jursa, Michael Toomim, Michael Willis, Michele Comitini, Miguel Goncalves, Miguel Lopez, Mike Amy, Mike Dickun, Mike Ellis, Mike Pechkin, Milan Melena, Muhammet Aydin, Napoleon Moreno, Nathan Freeze, Niall Sweeny, Niccolo Polo, Nick Groenke, Nick Vargish, Nico de Groot, Nico Zanferrari, Nicolas Bruxer, Nik Klever, Olaf Ferger, Oliver Dain, Olivier Roch Vilato, Omi Chiba, Ondrej Such, Ont Rif, Oscar Benjamin, Osman Masood, Ovidio Marinho Falcao Neto, Pai, Panos Jee, Paolo Betti, Paolo Caruccio, Paolo Gasparello, Paolo Valleri, Patrick Breitenbach, Pearu Peterson, Peli Gergely, Pete Hunt, Peter Kirchner, Phyo Arkar Lwin, Pierre Thibault, Pieter Muller, Piotr Banasziewicz, Ramjee Ganti, Richard Gordon, Richard Ree, Robert Kooij, Robert Valentak, Roberto Perdomo, Robin Bhattacharyya, Roman Bataev, Ron McOuat, Ross Peoples, Ruijun Luo, Running Calm, Ryan Seto, Salomon Derossi, Sam Sheftel, Scott Roberts, Sergey Podlesnyi, Sharriff Aina, Simone Bizzotto, Sriram Durbha, Sterling Hankins, Stuart Rackham, Telman Yusupov, Thadeus Burgess, Thomas Dallagnese, Tim Farrell, Tim Michelsen, Tim Richardson, Timothy Farrell, Tito Garrido, Tyrone Hattingh, Vasile Ermicioi, Vidul Nikolaev Petrov, Vidul Petrov, Vinicius Assef, Vladimir Donnikov, Vladyslav Kozlovsky, Vladyslav Kozlovskyy, Wang Huaiyu, Wen Gong, Wes James, Will Stevens, Yair Eshel, Yarko Tymciurak, Yoshiyuki Nakamura, Younghyun Jo, Zahariash.
Estoy seguro de que me olvido de alguien, así que pido disculpas.
Particularmente quiero agradecer a Anthony, Jonathan, Mariano, Bruno, Vladyslav, Martin, Nathan, Simone, Thadeus, Tim, Iceberg, Denes, Hans, Christian, Fran y Patrick por sus importantes contribuciones a web2py y a Anthony, Alvaro, Brian, Bruno, Denes, Dane Denny, Erwin, Felipe, Graham, Jonathan, Hans, Kyle, Mark, Margaret, Michele, Nico, Richard, Roberto, Robin, Roman, Scott, Shane, Sharriff, Sriram, Sterling, Stuart, Thadeus, Wen (y otros) por corregir varias versiones de este libro. Su colaboración es invaluable. Si encuentras algún error en este libro, es exclusivamente mi culpa, probablemente introducido en una edición de último minuto. También agradezco a Ryan Steffen de Wiley Custom Learning Solutions por su ayuda en la primera edición de este libro.
web2py contiene código de los siguientes autores, a los que quisera también agradecer:
Guido van Rossum por Python[python], Peter Hunt, Richard Gordon, Timothy Farrell por el servidor web Rocket[rocket] , Christopher Dolivet por EditArea[editarea], Bob Ippolito por simplejson[simplejson], Simon Cusack y Grant Edwards por pyRTF[pyrtf], Dalke Scientific Software por pyRSS2Gen[pyrss2gen], Mark Pilgrim por feedparser[feedparser], Trent Mick por markdown2[markdown2], Allan Saddi por fcgi.py, Evan Martin por el módulo memcache de Python[memcache], John Resig por jQuery[jquery].
Quiero agradecer a Helmut Epp (Rector de la Universidad DePaul), David Miller (Decano del Colegio de Computación y Medios Digitales de la Universidad DePaul), y Estia Eichten (Miembro de MetaCryption LLC), por su continua confianza y ayuda.
Por último, quisiera agradecer a mi esposa, Claudia, y a mi hijo, Marco, por tolerarme durante todo el tiempo que he empleado en el desarrollo de web2py, intercambiando correos con usuarios y colaboradores, y escribiendo este libro. Este libro está dedicado a ellos.