Pyramid: 6 - Forms (simpleform)
Aunque hasta ahora es cierto que hemos creado un model (bueno, dos), una view y una template, hemos configurado el root context de la aplicación y sabemos más o menos cómo funciona y cómo movernos por ella, de momento no hemos interactuado demasiado con el ZODB, nos falta agregar datos a ese modelo Twitts que creamos en su día y, obviamente, mostrarlos.
Para agregar datos necesitamos un formulario que mapee el modelo twitt en html y que el usuario pueda interactuar con él. Y aquí es donde entra en escena pyramid_simpleform. Como su nombre indica, se trata de una librería de validación y render de formularios que deberemos instalar en nuestro entorno:
$ pip install pyramid_simpleform
Una vez instalada ya podemos crear los formularios correspondientes. Para ello y por seguir alguna convención, usaremos el directorio schemas/, así que creamos dicho directorio, colocamos en él un __init__.py y, en principio, vamos a crear el formulario correspondiente al modelo twitt: twitt.py
# -*- coding: utf-8 -*-
from formencode import Schema, validators
class TwittSchema(Schema):
allow_extra_fields = True
filter_extra_fields = True
twitt = validators.UnicodeString(max=140)
Definido el schema del form, vamos a usarlo en una view, necesitamos importar las clases correspondientes, crear una instancia de ese formulario en base al esquema y pasarlo a template para renderizarlo en html:
# views/__init__.py
from pyramid_simpleform import Form, State
from pyramid_simpleform.renderers import FormRenderer
from src.schemas.twitt import TwittSchema
...
def homepage(context, request):
...
form = Form(request, schema=TwittSchema, multipart=True)
....
return {'form': FormRenderer(form),
'title': 'PyTwitter',
'description': 'Our twitter clon, with Pyramid'}
En nuestro index.pt agregamos el formulario propiamente dicho y ya debería aparecer algo parecido a lo siguiente:
# templates/index.pt
<title$>{title}</title>
<p>${description}</p>
<hr />
${form.begin()}
${form.text('twitt')}
${form.errorlist('twitt')}
${form.submit('submit', 'Submit')}
${form.end()}
Ahora tan solo nos queda la segunda parte, recoger los datos por POST y agregarlos persistentemente a nuestra ZODB. Para ello comprobamos en view si existe algún dato request.POST y si valida adecuadamente. Finalmente llamaremos al método add_twitt() del context para que lo agregue a la base de datos:
# views/__init__.py
if 'submit' in request.POST and form.validate():
twitt = form.bind(Twitt())
twitt.published = datetime.today()
context.add_twitt(twitt)
# models/rootfolder.py
def add_twitt(self, twitt):
self.add(str(twitt.tid), twitt)
Y por último, si queremos sacar todos los twitts que hemos guardado, llamaremos a un método del model que nos los devuelva y el procedimiento es el mismo siempre, pasarlos a template para pintarlos:
# models/rootfolder.py
@property
def index(self):
return [t for t in self.values() if isinstance(t, Twitt)]
# views/__init__.py
...
twitts = context.index
...
return {'form': FormRenderer(form),
'twitts': twitts,
'title': 'PyTwitter',
'description': 'Our twitter clon, with Pyramid'}
# templates/index.pt
<hr />
<ul>
<li tal:repeat="twit twitts">${twit.twitt} (${twit.published})</li>
</ul>
Ahora sí que tenemos nuestra primera interacción con ZODB completa y funcional. Ya podemos agregar nuevos twitts y ver el listado de los mismos. Ahora faltaría, de alguna forma, ponerlo un poco más bonito. En la próxima entrada hablaremos de bootstrap, fontawesome, bower y webassets.