desarrollando aplicaciones web con zope 3

77
corporate training menttes Pablo Ambrosio [email protected] Desarrollando aplicaciones web con Zope 3

Upload: roberto-allende

Post on 23-Jan-2015

2.896 views

Category:

Business


2 download

DESCRIPTION

Charla de introducción a zope3: Qué es Zope 3 - Propositos de la plataforma, Aplicación, Qué es Grok, como desarrollar una aplicación con Grok, vistas, zcmls, expresiones tal, generando html desde python, formularios, almacenamiento de datos, contenedores,

TRANSCRIPT

Page 1: Desarrollando aplicaciones web con Zope 3

corporate training menttes

Pablo Ambrosio [email protected]

Desarrollando aplicaciones web con Zope 3

Page 2: Desarrollando aplicaciones web con Zope 3

menttes

Que es Zope 3?Zope 3 es un framework de aplicaciones web open source escrito en el lenguaje Python, especialmente apto para desarrollar aplicaciones de manejo de contenido (content management system), intranets, portales.

Provee un arquitectura de componentes y una base de datos transaccional orientada a objetos.

El diseño de Zope 3 esta influenciado por practicas de desarrollo como programación ágil y testeo automatizado.

Page 3: Desarrollando aplicaciones web con Zope 3

menttes

Quienes y cuando...

Inicialmente la tecnología Zope fue diseñada por la Zope Corporation. 

El desarrollo de Zope 3 comenzo a fines del 2001, y fue lanzado en Noviembre del 2004. Basandose en la experiencia de Zope 2 fue totalmente reescrito, solo conservando su base de datos ZODB.

Es desarrollado por una comunidad libre donde la practica de Sprints es comun.

En el 2006 se crea la Zope foundation para promover la plataforma y proveer soporte a la comunidad.

Page 4: Desarrollando aplicaciones web con Zope 3

menttes

Propósitos de la plataforma

● Proveer un entorno de desarrollo atractivo para desarrolladores Python y otros desarrolaldores

● Facilitar la creación de objetos utilizables en Zope:● Posibilitando el uso de clases Python preexistentes● Usando las prestaciones del framework en forma incremental y gradual

● Facilitar la curva de aprendizaje

Page 5: Desarrollando aplicaciones web con Zope 3

menttes

Propósitos de la plataforma

● Facilitar el reuso del software● Usando objetos externos a Zope● Agregando, quitando o reemplazando funcionalidades de los objetos existentes.● Proveyendo métodos alternativos de acceso a los objetos (FTP, XML­RPC)

● Aplicando las lecciones aprendidas usando y construyendo Zope 2

● Proveyendo soporte para internacionalización y localización

● Integrando patrones de diseño en Zope

Page 6: Desarrollando aplicaciones web con Zope 3

menttes

¿Esta Zope 3 listo para entornos de producción?

Zope 3 se usa en varios sitios de produccion de tamaño considerable. Algunas aplicaciones públicas incluyen:

●  Launchpad

●  SchoolTool

Page 7: Desarrollando aplicaciones web con Zope 3

menttes

Page 8: Desarrollando aplicaciones web con Zope 3

menttes

Page 9: Desarrollando aplicaciones web con Zope 3

menttes

Page 10: Desarrollando aplicaciones web con Zope 3

menttes

Grok

Grok es Zope 3 simplificado.

Fue creado para acortar el tiempo que toma volverse productivo en Zope 3 y disminuye las lineas de código a escribir reemplazando los temidos archivos ZCML.

Es un framework (si, otro).

Page 11: Desarrollando aplicaciones web con Zope 3

menttes

¿Que necesitamos saber?

Nos alcanza con conocer el lenguage de programación Python y un entendimento básico de programación web (HTML, forms, URLs).

Para ver como Grok nos puede ayudar a construir nuestra aplicación web, comenzaremos con las cosas simples, para luego ir a hacia usos mas complejos.

Page 12: Desarrollando aplicaciones web con Zope 3

menttes

Instalando GrokNecesitaremos:

● Conexión a internet, ya que Grok se instala a traves de la red.● Python 2.4 instalado.

Como grok utiliza código fuente de Zope 3 para su distribución:

● Python "dev" package.● Compilador C (tipicamente gcc) instalado.● easy_install, para poder trabajar con “eggs”.

Listo?

$ sudo easy_install grokproject

Page 13: Desarrollando aplicaciones web con Zope 3

menttes

Creando un proyecto

Un proyecto en Grok es un entorno de desarrollo completo.

$ grokproject Sample

Esto creara un nuevo subdirectorio llamado “Sample”, e instalará el proyecto allí. grokproyect automáticamente baja e instala Zope 3 y Grok dentro del directorio. 

Luego de proveer el nombre del módulo, al que llamaremos “app.py” (provisto por defecto) y un nombre de usuario y password inicial, estamos listos para comenzar.

Page 14: Desarrollando aplicaciones web con Zope 3

menttes

La instancia Zope

$ cd Sample

Desde alli podemos levantar nuestra instancia Zope:

$ parts/instance/bin/zopectl fg

Zope 3 estara disponible en el puerto 8080, nos logeamos ingresando el usuario y contraseña ya indicados:

http://localhost:8080

Page 15: Desarrollando aplicaciones web con Zope 3

menttes

Page 16: Desarrollando aplicaciones web con Zope 3

menttes

http://localhost:8080/test

Page 17: Desarrollando aplicaciones web con Zope 3

menttes

La aplicación

Las fuentes de nuestra aplicacion se encuentran en /src/sample :

..app.pyapp_templatesconfigure.zcml__init__.pyREADME.txtstatic

Grok sabe como asociar el directorio con el módulo según el nombre.

Veamos el código de nuestra aplicación, app.py.

Page 18: Desarrollando aplicaciones web con Zope 3

menttes

La aplicación

import grok

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    pass # see app_templates/index.pt

Suficiente para mostrar la página de bienvenida.

Page 19: Desarrollando aplicaciones web con Zope 3

menttes

El TemplateEn el directorio app_templates vamos a encontrar el template index.pt:

<html><head></head><body>  <h1>Congratulations!</h1>

  <p>Your Grok application is up and running.  Edit <code>sample/app_templates/index.pt</code> to change  this page.</p></body>

Esta es nuestra página de bienvenida.

http://localhost:8080/test

Page 20: Desarrollando aplicaciones web con Zope 3

menttes

ZCML (Zope Configuration Markup Language)Pondremos en el directorio de la aplicacion el archivo de configuración configure.zcml. A diferencia de otras aplicaciones Zope 3, este solo contiene una línea que cumple la función de registrar la aplicación.

Podemos ignorar este archivo durante el desarrollo, grok se encarga de hacer la configuración por nosotros

<grok package="." xmlns="http://namespaces.zope.org/grok" />

Page 21: Desarrollando aplicaciones web con Zope 3

menttes

Agregando views (vistas)Nuestro view se llama index. Esto significa que es la vista por defecto. Tambien puede ser accedida explicitamente:

    http://localhost:8080/test/index

Creamos un segundo template llamado bye.pt en app_templates con el siguiente contenido:

<html><body>

<p>Chau mundo...</p></body></html>

Page 22: Desarrollando aplicaciones web con Zope 3

menttes

Agregando views

Para decirle a Grok que use este template modificaremos app.py:

import grok  

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    pass

class Bye(grok.View):    pass

Page 23: Desarrollando aplicaciones web con Zope 3

menttes

Agregando views

Una vista (view) es una forma de ver un modelo, en este caso nuestra aplicación Sample. 

La definicion de clase vacía es suficiente para que Grok busque en app_templates por bye.pt.

La regla es que un template debe tener el mismo nombre que su clase asociada, con minúsculas:

    http://localhost:8080/test/bye

Los URL en Zope son case sensitive.

En este punto habrá que reiniciar Zope.

Page 24: Desarrollando aplicaciones web con Zope 3

menttes

Expresiones TAL

Los Zope Page Templates son documentos XHTML, lo que significa que pueden ser vistos y editados usando herramientas compatibles con XHTML.

ZPT (Zope Page Templates) esta basado en los lenguajes TAL (Template Attribute Language) y METAL (Macro Expansion Template Attribute Language), ambos son específicos de Zope. 

Existen varias implementaciones en Python y en otros lenguajes. Puede ser usado con otras aplicaciones.

Page 25: Desarrollando aplicaciones web con Zope 3

menttes

Template Attribute Language (TAL)

El Template Attribute Language (TAL) es un lenguaje expresado como atributos en las etiquetas (tags) HTML.

Las etiquetas tienen la forma:

<p tal:comando="expresion">Texto</p>

Todas las declaraciones en TAL consisten de atributos en etiquetas cuyos nombres comienzan con “tal:” , y todas tienen valores asociados, que siempre van entre comillas.

Estas etiquetas son código HTML válido, o sea que estos documentos se pueden editar con cualquier editor de HTML.

Page 26: Desarrollando aplicaciones web con Zope 3

menttes

Expresiones TAL● path, describen una caminata desde un objeto hacia otro.

“view/current_time”

● string, permiten combinar fácilmente expresiones path y texto

"string:La fecha es ${view/current_time}."

● python, puede contener cualquier cosa que el lenguaje Python  considere una expresión. No se pueden usar declaraciones como if o while.

“python:year != 2005”

● otras... (Exists, Not)

Page 27: Desarrollando aplicaciones web con Zope 3

menttes

Comandos TAL

●  define

●  condition

●  repeat

●  content

●  replace

●  attributes

Page 28: Desarrollando aplicaciones web con Zope 3

menttes

Propiedades de los Page Templates

El mecanismo de XML y HTML de Zope:

● conserva el template como código XML bien formado

● intenta ser no invasivo usando atributos registrados como   namespaces (TAL) 

● provee soporte para macros (METAL)

● provee soporte de para internacionalización

Page 29: Desarrollando aplicaciones web con Zope 3

menttes

Haciendo páginas dinámicasUsaremos directivas de Zope Page Templates (ZPT) para generar contenidos dinámicos. Cambiando index.pt:

<html><body>

<p tal:content="python: 1 + 1">esto se reemplaza</p></body></html>

El código fuente se verá así:

<html><body>

<p>2</p></body></html>

Page 30: Desarrollando aplicaciones web con Zope 3

menttes

Recursos estáticos para nuestras páginas

Usualmente necesitaremos referirnos a recursos en nuestras páginas, como imágenes, archivos CSS y código Javascript. Como ejemplo agregemos un poco de estilo en nuestra página

Creamos un directorio nuevo llamado “static” en el “sample package” (src/sample/static). Dentro creamos un archivo llamado style.css:

body {    background­color: #FF0000;}

Page 31: Desarrollando aplicaciones web con Zope 3

menttes

Recursos estáticos para nuestras páginasPara usarlo, lo referimos desde index.pt:

<html><head>

<link rel="stylesheet" type="text/css"        tal:attributes="href static/style.css" />

</head><body>

<p>Hola mundo!</p></body></html>

Notar el uso de la directiva tal:attributes. Usamos Zope Page Templates para generar dinámicamente el enlace al archivo style.css.

Page 32: Desarrollando aplicaciones web con Zope 3

menttes

Recursos estáticos para nuestras páginas

El código fuente se verá asi:

<html><link rel="stylesheet" type="text/css"

       href="http://localhost:8080/test/@@/sample/style.css" /><body>

<p>Hola mundo!</p></body></html>

Igualmente poniendo los archivos de imágenes o los .js en el directorio “static” y creando el URL a ellos usando static/<archivo> en el page template.

Page 33: Desarrollando aplicaciones web con Zope 3

menttes

Usando métodos view

ZPT esta deliberadamente limitado en cuanto a lo que permite hacer con Python. Es una buena práctica de diseño hacer cualquier cosa que sea un poco mas complicada con código Python.

Usar código Python arbitrariamente desde ZPT es fácil, agregamos métodos a la clase view y los usamos desde el template.

Si quisieramos mostrar la fecha actual...

>>> from datetime import datetime

esta declaración esta fuera de las capacidades de los ZPT, no esta permitido importar módulos dentro de un template.

Page 34: Desarrollando aplicaciones web con Zope 3

menttes

Usando métodos view

Integremos un poco de código en nuestro proyecto Grok. Modificando app.py:

import grokfrom datetime import datetime

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):        def current_datetime(self):        now = datetime.now()        return now.strftime('%Y­%m­%d %H:%M')

Page 35: Desarrollando aplicaciones web con Zope 3

menttes

Usando métodos view

Hemos agregado un método que devuelve un string. Ahora mostremos este string en la página index.pt:

<html><body>

<p tal:content="python:view.current_datetime()">Hola</p></body></html>

veremos algo como:

2007­02­27 17:21

Page 36: Desarrollando aplicaciones web con Zope 3

menttes

Usando métodos view

Una forma un poco mas corta y mas sencilla de leer a veces en ZPT es usando una expresion path:

<html><body>

<p tal:content="view/current_datetime"></p></body></html>

Corriendo esto se obtiene el mismo resultado que en el caso anterior.

Page 37: Desarrollando aplicaciones web con Zope 3

menttes

Generando HTML desde PythonA veces se obtendra o generara HTML desde código Python para luego incluirlo en una página. Por razones de seguridad contra cross­scripting TAL automaticamente escapa HTML &gt; y &lt;. Con la directiva “structure” se le puede decir explícitamente a TAL que no escape HTML, asi se puede pasara literalmente al template:

import grok  

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    def some_html(self):        return "<b>YO GROK BOLD</b>"

Page 38: Desarrollando aplicaciones web con Zope 3

menttes

Generando HTML desde Python

Y cambiamos index.pt de la siguiente manera:

<html><body>

<p tal:content="structure python:view.some_html()"></p></body></html>

veremos el texo:

YO GROK BOLD

el HTML generado fue integrado en la página. Sin la directiva “structure” se vería algo como:

<b>YO GROK BOLD</b>

Page 39: Desarrollando aplicaciones web con Zope 3

menttes

Views completamente dirijidas con Python

A veces es inconveniente usar templates. Tal vez ni siquiera estamos devolviendo una página HTML. En estos casos se peude usar el método render en la view:

import grok  

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    def render(self):        return "YO GROK SIN TEMPLATE"

En este caso queda el template index.pt dando vueltas, ante la ambiguedad Grok se niega a adivinar, luego habra que remover el template.

Page 40: Desarrollando aplicaciones web con Zope 3

menttes

Configurando el content-typeCuando se genera el contenido desde el view puede ser útil cambiarlo a otra cosa que no sea text/plain:

import grok  

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    def render(self):        self.response.setHeader('Content­Type',

                                 'text/xml; charset=UTF­8')        return "<doc>Un poco de XML</doc>"

Todas las vistas en Grok tienen la propiedad “response” que se puede usar para manipular los headers de respuesta.

Page 41: Desarrollando aplicaciones web con Zope 3

menttes

Haciendo cálculos antes de ver una páginaPodemos hacer que el view haga ciertos cálculos para nuestra página y asi hacer el cálculo una vez por recarga (aunque usemos el valor múltiples veces en la página).

Esto se puede hacer usando el método update en la clase de la vista:

import grok

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    def update(self):        self.alpha = 2 ** 8

Esto setea “alpha” en la vista justo antes de que se muestre el template. 

Page 42: Desarrollando aplicaciones web con Zope 3

menttes

Haciendo cálculos antes de ver una página

Necesitaremos un template index.pt que use alpha:

<html><body>

<p tal:content="python:view.alpha">resultado</p></body></html>

Page 43: Desarrollando aplicaciones web con Zope 3

menttes

Leyendo parámetros URL

Usualmente cuando desarrollemos nuestra aplicación vamos a querer no solo mostrar datos, sino tambien recibirlos (y procesarlos). Una forma simple de hacer esto es obteniendo la informacion como parámetros en un URL. 

Hagamos una aplìcacion que resuelva sumas. Si le pasamos el siguiente URL a la aplicación:

    http://localhost:8080/test?value1=3&value2=5

deberíamos obtener su suma (8) como resultado en la página.

Page 44: Desarrollando aplicaciones web con Zope 3

menttes

Leyendo parámetros URL

Modificamos app.py para que se vea asi:

import grok

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    def update(self, value1, value2):        self.sum = int(value1) + int(value2)

Page 45: Desarrollando aplicaciones web con Zope 3

menttes

Leyendo parámetros URL

Necesitaremos un index.pt que use sum:

<html><body>

<p tal:content="python:view.sum">suma</p></body></html>

Otras sumas funcionaran por supuesto:

    http://localhost:8080/test?value1=50&value2=50

Page 46: Desarrollando aplicaciones web con Zope 3

menttes

Leyendo parámetros URL

Sino pasamos parámetros por el URL (value1 y value2) obtendremos un error:

A system error occurred.

En el traceback donde corremos el Zope veremos:

TypeError: Missing argument to update(): value1

Este es el mensaje de error relevante.

Page 47: Desarrollando aplicaciones web con Zope 3

menttes

Leyendo parámetros URL

Modificamos el codigo para que funcione aunque no preoveamos parámetros:

import grok

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    def update(self, value1=0, value2=0):        self.sum = int(value1) + int(value2)

Page 48: Desarrollando aplicaciones web con Zope 3

menttes

Formularios simplesUsemos un formulario para pasar los parámetros. Cambiamos index.pt para que contenga un formulario como:

<html><body>

<form tal:attributes="action python:view.url()" method="GET">  Valor 1: <input type="text" name="value1" value="" /><br />  Valor 2: <input type="text" name="value2" value="" /><br />  <input type="submit" value="Sumar!" />

</form><p>La suma es: <span tal:replace="python:view.sum">suma</span></p>

</body></html>

Page 49: Desarrollando aplicaciones web con Zope 3

menttes

Formularios simples

<form tal:attributes="action python:view.url()" method="GET">

Un detalle para notar en este código es que generamos la acción del formularion dinámicamente. Básicamente le decimos al formulario que se reenvíe a si mismo. El método url, propio de Grok, nos permite obtener el URL de la misma vista (y otros URLs tambien).

Todavía tenemos algunos problemas con ese código. Si no cargamos parámetros y enviamos el formulario obtendremos un error como el siguiente:

File "../app.py", line 8, in update  self.sum = int(value1) + int(value2)ValueError: invalid literal for int():

Page 50: Desarrollando aplicaciones web con Zope 3

menttes

Formularios simples

Si los parámetros son string vacíos no podrán ser convertidos a enteros. Otra cosa poco simpática es que mostramos una suma (0) aun cuando no proveeemos datos:

class Index(grok.View):    def update(self, value1=None, value2=None):        try:            value1 = int(value1)            value2 = int(value2)        except (TypeError, ValueError):            self.sum = "No hay suma"            return        self.sum = value1 + value2

En Grok uno puede usar las bibliotecas schema y formlib de Zope 3 para automatizar la generacion de formularios.

Page 51: Desarrollando aplicaciones web con Zope 3

menttes

Modelos

Hemos visto como mostrar páginas web, ahora veremos un poco mas sobre lo que estamos mostrando: el modelo. El modelo contiene la lógica de la aplicación, independientemente de la vista.

La vista, junto con el template, es responsable de mostrar la información y su interfaz de usuario. El modelo representa la información (o contenido) de los que trata la aplicación , como documentos, entradas de blog o páginas wiki. El modelo no debe saber nada sobre como son mostrados los datos. 

En una aplicacion Grok, los modelos se definen como subclases de grok.Model o grok.Container. 

Page 52: Desarrollando aplicaciones web con Zope 3

menttes

La vista para un modeloLa clase Sample es un grok.Container, asi que la usaremos para ver los principios básicos de modelos. Modifiquemos app.py para que tenga información disponible:

import grok

class Sample(grok.Application, grok.Container):    def information(self):        return "Esta es informacion del modelo"

class Index(grok.View):    pass

En este caso, la información esta hardcodeada, pero podemos imaginar que la estamos extrayendo de algun otro lado, como una base de datos o el file system.

Page 53: Desarrollando aplicaciones web con Zope 3

menttes

La vista para un modelo

Si quisieramos ver esta informacion en nuestro template index.pt:

<html><body>

<p tal:content="python:context.information()">reemplazado</p></body></html>

Vimos que se pueden acceder métodos y atributos de una vista usando la palabra clave view en un template.

De la misma manera la palabra context esta disponible en cada template, y nos permite acceder informacion en el objeto contextual que la vista esta mostrando. En este caso una instancia de Sample.

Page 54: Desarrollando aplicaciones web con Zope 3

menttes

La vista para un modelo

Hagamos que la vista modifique la forma en que vemos la información (sin modificar los datos del modelo claro). Cambiemos app.py:

import grok

class Sample(grok.Application, grok.Container):    def information(self):

         return "Esta es información del modelo"

class Index(grok.View):    def reversed_information(self):        return ''.join(reversed(self.context.information()))

El objeto context tambien puede ser accedido desde la clase de la vista.

Page 55: Desarrollando aplicaciones web con Zope 3

menttes

Almacenando datos

¿Que tal si quisieramos almacenar alguna información? Como algun dato ingresado por el usuario. La forma mas sencilla de hacer esto con Zope es usando la Zope Object DataBase (ZODB).

La ZODB es una base de datos de objetos Python. Se puede almacenar cualquier objeto Python en ella siempre que se sigan algunas simples reglas (las “Reglas de Persistencia”). Nuestro objeto de aplicacion Sample está almacenado en la base de datos, luego podemos almacenar información en él.

Page 56: Desarrollando aplicaciones web con Zope 3

menttes

Almacenando datos

Creemos una aplicación que almacene un tramo de texto. Usaremos una vista para visualizar el texto (index) y otra para editarlo (edit). Esta es app.py:

import grok

class Sample(grok.Application, grok.Container):    text = 'texto por defecto'

class Index(grok.View):    pass

class Edit(grok.View):    def update(self, text=None):        if text is None:            return        self.context.text = text

Page 57: Desarrollando aplicaciones web con Zope 3

menttes

Almacenando datos

Esto setea el atributo text en la instancia del objeto Sample en la base de datos, sobreescribiendo el texto por defecto de la clase. Cambiamos el template index.pt para que se lea:

<html><body>

<p>El texto: <span tal:replace="python:context.text">texto</span></p><p><a tal:attributes="href python:view.url('edit')">Edit this page</a></p>

</body></html>

Dándole al método url un string como argumento generará un URL a la vista llamada como el string en el mismo objeto (test), en este caso test/edit.

Page 58: Desarrollando aplicaciones web con Zope 3

menttes

Template de ediciónCreamos un template edit.pt con el siguiente contenido:

<html><body>

<form tal:attributes="action view/url" method="POST">Texto a guardar: <input type="text" name="text" value="" /><br /><input type="submit" value="Store" />

</form></body></html>

La página se reenvía a si misma y se verá el texto ingresado. Esto significa que el texto esta almacenado en la base de datos.

http://localhost:8080/test

Se puede reiniciar Zope y volver a la página index y se verá que los cambios persisten.

Page 59: Desarrollando aplicaciones web con Zope 3

menttes

Redireccion

Cambiemos el formulario de edit para que redirija devuelta a la página de index luego de presionado el boton submit:

class Edit(grok.View):    def update(self, text=None):        if text is None:            return        self.context.text = text        self.redirect(self.url('index'))

La última línea es la nueva. Usamos el método url en la vista para construir el URL de la página index. Dado que estamos en un template, podemos llamar el método sobre self. Luego se lo pasamos a otro método disponible en todas las subclases de grok.View, redirect.

Page 60: Desarrollando aplicaciones web con Zope 3

menttes

Reglas de persistencia

● Para almacenar datos de una clase en la ZODB debemos hacerla subclase de persistent.Persistent. La forma mas sencilla de hacer esto con Grok es hacerla subclase de grok.Model o grok.Container.

Page 61: Desarrollando aplicaciones web con Zope 3

menttes

Reglas de persistencia

● Para almacenar instancias éstas deben estar conectadas a otras clases persistentes que ya esten almacenadas. La forma mas simple con Grok es agregarlas de alguna forma al objeto grok.Application, directa o indirectamente. Esto se hace seteandolas como un atributo o poniéndolas en un contenedor (si hacemos la aplicacion subclase de grok.Container).

Page 62: Desarrollando aplicaciones web con Zope 3

menttes

Reglas de persistencia

● Para asegurarse que la ZODB se entere que se ha cambiado un objeto mutable (como una lista o diccionario Python) en una instancia, se setea el atributo _p_changed en esa instancia a True. Esto solo es necesario cuando el atributo no es persistente por si mismo. Tampoco es necesario cuando se crea o sobreescribe un atributo directamente usando =.

Page 63: Desarrollando aplicaciones web con Zope 3

menttes

Reglas de persistencia

Si se construye el contenido de la aplicación con subclases de  grok.Model y grok.Container prácticamente se siguen todas las reglas.

Si usamos un objeto mutable como una lista o un diccionario para almacenar datos necesitamos tomar una acción especial. Modificando el código anterior para usar una lista:

class Sample(grok.Application, grok.Container):    def __init__(self):        super(Sample, self).__init__()        self.list = []

Page 64: Desarrollando aplicaciones web con Zope 3

menttes

Reglas de persistencia

def addText(self, text):         self.list.append(text)

        self._p_changed = True        

class Edit(grok.View):    def update(self, text=None):        if text is None:            return        self.context.addText(text)        self.redirect(self.url('index'))

Creamos un método addText en el modelo que se encarga de actualizar la lista e informar a la ZODB de esto. Asi cualquier código de vista puede usar la API de Sample sin preocuparse por las reglas de persistencia, ya que es una responsabilidad del modelo.

Page 65: Desarrollando aplicaciones web con Zope 3

menttes

Reglas de persistencia

Modificamos index.pt para que muestre la lista:

<html><body>

Se guardaron los textos:<ul>  <li tal:repeat="text python:context.list" tal:content="text"></li></ul>

<a tal:attributes="href python:view.url('edit')">Agregar un texto</a>

</body></html>

Page 66: Desarrollando aplicaciones web con Zope 3

menttes

Asociando explícitamente una vista a un modelo

Como sabe Grok que una vista pertenece a un determinado modelo? En los ejemplos vistos Grok hace esta asociacion automáticamente. Esto se pudo hacer porque solo hay un modelo definido en el módulo (Sample). Detras de escena Grok hizo al modelo ser el context de todas las vistas.

Todo lo que Grok hace implícitamente también se puede hacer explícitamente. Esto es útil cuando se necesite decirle a Grok que hacer, sobreescribiendo el comportamienteo por defecto. Para asociar una vista con un modelo se usa la anotacion de clase grok.context.

Una anotacion de clase es una forma declarativa de decirle a Grok algo acerca de una clase Python.

Page 67: Desarrollando aplicaciones web con Zope 3

menttes

Asociando explícitamente una vista a un modelo

Sea la siguiente app.py:

import grok  

class Sample(grok.Application, grok.Container):    pass

class Index(grok.View):    grok.context(Sample)

class Bye(grok.View):    grok.context(Sample)

Lo único hecho es poner explícita la relación entre el modelo y la vista, usando la directiva grok.context.

Page 68: Desarrollando aplicaciones web con Zope 3

menttes

Contenedores

Un contenedor es un tipo especial de objeto modelo que puede contener otros objetos. La aplicación Sample es un contenedor, al ser subclase de grok.Container. 

Una aplicación Grok está típicamete compuesta por contenedores y modelos. Con modelos siendo contenidos en dichos contenedores. A su vez los modelos contenidos tambien pueden ser contenedores, ya que estos son a su vez modelos.

Page 69: Desarrollando aplicaciones web con Zope 3

menttes

Contenedores

Desde la perspectiva Python, se puede pensar en contenedores como diccionarios. Permiten acceso por item (container['key']) para obtener sus contenidos. Tambien definen métodos como keys() y values().

Los contenedores ademas proveen otras funcionalidades propias. Son persistentes, y cuando son modificados no es necesario usar el atributo _p_changed. Tambien implementan eventos especiales que pueden ser escuchados cuando nuevos items son agregados en los contenedores o removidos.

Page 70: Desarrollando aplicaciones web con Zope 3

menttes

ContenedoresProbemos un objeto de aplicación que tenga una página index donde se muestran sus contenidos. Se puede seleccionar un item del contenido para verlo. Bajo la lista habrá un formulario que premita agregar nuevo contenido. Este será app.py:

import grok

class Sample(grok.Application, grok.Container):    pass

class Entry(grok.Model):    def __init__(self, text):        self.text = text

Hemos creado un objeto que no es de aplicación, Entry. Es sólo un grok.Model. Necesita ser creado con un texto como argumento al cual almacena.

Page 71: Desarrollando aplicaciones web con Zope 3

menttes

Contenedores

class SampleIndex(grok.View):    grok.context(Sample)    grok.name('index')

    def update(self, name=None, text=None):        if name is None or text is None:            return        self.context[name] = Entry(text)

Luego siguen las vistas. Habra una para el contenedor Sample. Cuando su update es llamado con dos valores, name y text, creara una nueva instancia de Entry con el texto dado, y la pondra en el contenedor con el nombre name. Se usa la notacion tipo diccionario para agregar la nueva Entry en el contenedor.

Page 72: Desarrollando aplicaciones web con Zope 3

menttes

Contenedores

class EntryIndex(grok.View):    grok.context(Entry)    grok.name('index')

Hay otro detalle, la idea es que estas vistas sean de tipo index. Esto no se puede deducir automáticamente por el nombre de las clases, sin embargo, si lo dejamos solo Grok hubiese llamado a las vistas sampleindex y entryindex.

Para este caso existe otra anotacion de clase que puede ayudar, grok.name. Se puede usar en ambas clases (grok.name('index')) para decirle explícitamente a Grok lo que queremos.

Page 73: Desarrollando aplicaciones web con Zope 3

menttes

Contenedores

Este es el template asociado con SampleIndex, sampleindex.pt:

<html><head></head><body>  <h2>Entradas existentes</h2>  <ul>    <li tal:repeat="key python:context.keys()">      <a tal:attributes="href python:view.url(key)"          tal:content="python:key"></a>    </li>  </ul>

Usamos keys() para obtener la lista de todos los nombres de los items en el contenedor. Creamos un link a los items usando view.url().

Page 74: Desarrollando aplicaciones web con Zope 3

menttes

Contenedores

  <h2>Agregar nueva entrada</h2>  <form tal:attributes="action python:view.url()" method="POST">    Nombre: <input type="text" name="name" value="" /><br />    Texto: <input type="text" name="text" value="" /><br />    <input type="submit" value="Agregar entrada" />  </form>

</body>

En esta sección se muesta un formulario que envía los datos a la propia página index. Tiene dos campos, name y text, que son manejados por update().

Page 75: Desarrollando aplicaciones web con Zope 3

menttes

ContenedoresFinalmente, una página index para Entry. Tiene un template para mostrar el atributo text:

<html><head></head><body>  <h2>Entrada <span tal:replace="python:context.__name__">

</span>        </h2>

  <p tal:content="python:context.text"></p></body>

      </html>

Reiniciamos Zope y probamos la aplicación.

Page 76: Desarrollando aplicaciones web con Zope 3

menttes

Page 77: Desarrollando aplicaciones web con Zope 3

menttes

Referencias

● www.zope.org 

● www.archive.org/details/grok_todo_part1

● grokzope.org

● worldcookery.com

● wiki.zope.org/zope3

● www.zope.org/Documentation/Books/ZopeBook/2_6Edition/ZPT.stx

● www.zope.com

● www.schooltool.org

● launchpad.net  paleosoft.org  foundation.zope.org