oscarmlage oscarmlage

Pyramid: 4 - Models

Written by oscarmlage on

Si hacemos memoria, hasta el momento ya sabemos montar un proyecto y un entorno mínimo de trabajo, entendemos la estructura del mismo, incluso nos hemos arriesgado a modificarla ligeramente según nuestras necesidades; y sabemos a pies juntillas cómo funciona el despachador de urls de Traversal contra la ZODB.

Es el momento de crear nuestro primer modelo de datos. Los modelos indican la forma en la que vamos a guardar los datos de nuestra aplicación en la ZODB así que son una parte crucial en la que debemos tener especial cuidado.

La idea en la que vamos a trabajar para entender el modo de funcionamiento es algo sencillo, un trivial clon de Twitter en el que podamos actualizar nuestro estado y ver todos los estados anteriores que hemos escrito. Luego, si hay tiempo y ganas, lo iremos complicando poco a poco.

Pensando un poco en las propiedades de este modelo vamos a definirlo de forma que tenga id, twitt y published (fecha de publicación). Para crearlo nos vamos al directorio models/ y dentro de un nuevo fichero twitt.py agregamos el siguiente contenido:

# -*- coding: utf-8 -*-

from uuid import uuid1
from persistent import Persistent

class Twitt(Persistent):

    def __init__(self, **kwargs):
        self.tid = uuid1()
        self.twitt = kwargs.get('twitt', None)
        self.published = kwargs.get('published', None)
        super(Twitt, self).__init__()

Como vemos no se trata más que de una clase normal en Python que hereda de Persistent y tiene las propiedades que hemos descrito anteriormente. ¿Sencillo?, pues ya tenemos nuestro primer modelo. Además y como trabajo extra vamos a intentar montar un modelo a mayores que sea el "root" de la aplicación. Esto significa que cuando entremos a la aplicación, por defecto, nos responda ese modelo.

Un modelo de ese tipo tiene que tener ciertas propiedades especiales, por eso, habitualmente para la petición principal de la aplicación se utiliza un modelo de tipo Folder (repoze.folder). Como nosotros vamos a darle ciertas propiedades o métodos especiales, en vez de usar Folder directamente, vamos a extender su funcionamiento. Creamos en models/ nuestro rootfolder.py que actuará como punto de entrada a la aplicación:

# -*- coding: utf-8 -*-

from repoze.folder import Folder
from src.models.twitts import Twitt

class RootFolder(Folder):

    def __init__(self):
        super(RootFolder, self).__init__()

Ojo: Para usar repoze.folder es posible que tengamos que instalarlo en nuestro entorno: pip install repoze.folder

Una vez tenemos este modelo "especial" preparado debemos configurar el objeto app_root que tendremos dentro del método app_maker() especificándole que RootFolder() será lo primero que vea la aplicación. Yo tengo este método en views/__init__.py, pero hay gente que trabajando con ZODB acostumbra a ponerlo en el models.py:

def appmaker(zodb_root):
    if not 'app_root' in zodb_root:
        app_root = RootFolder()
        zodb_root['app_root'] = app_root
        import transaction
        transaction.commit()
    return zodb_root['app_root']

Tip: Una forma de comprobar que todo está funcionando (no siempre pasa a la primera) es entrar vía pshell y comprobar que realmente está cargando el root que le hemos configurado. Si no lo hace puede ser que Data.fs esté corrupto porque se ha creado anteriormente y debamos eliminarlo/migrarlo. Para comprobarlo por pshell podemos hacer lo siguiente:

$ pshell development.ini
>>> root
<src.models.rootfolder.RootFolder object None at 0x11037b758>

Hasta aquí ya hemos creado nuestro primer modelo, un segundo modelo "especial" basado en repoze.folder para el root de nuestra aplicación, y hemos empezado a usar la shell interactiva. En la siguiente entrada veremos cómo escribir una view y una template con Chameleon.