Usare YAFOWIL per creare form in Plone

Un introduzione all'uso della libreria YAFOWIL per creare form personalizzati in Plone

YAFOWIL é un libreria Python 'framework-agnostic' (cioé indipendente dal sistema nel quale lo si vuole utilizzare, sia esso Plone, Pyramid, Django o altro framework Python) il cui scopo é semplificare il modo di creare form personalizzati.

É stato creato dall'ottimo team di Blue Dynamic Alliance e sebbene il suo nome sia un po' buffo ("Yet Another FOrm WIdget Library", "Ancora un'altra libreria per widget di un form") é uno strumento molto potente e flessibile per ottenere le nostre form.

In questo breve esempio apprezzeremo la sua semplicitá per creare una form in Plone.

La prima cosa da notare é che il design della form é molto pythonico. Essa é essenzialmente un dizionario dove ogni chiave corrisponde a un elemento della form, sia esso un campo o un bottone.

Notare che ho detto 'elemento' e non 'campo' dato che in potenza potremmo creare qualsiasi tipo di elemento html (si rimanda alla documentazione).

Creiamo una semplice form in Plone

Prima di tutto carichiamo un po di componenti:

import yafowil.plone
import yafowil.loader
from yafowil.base import factory
from yafowil.plone import form

e defininiamo la vista facendola ereditare da yafowil.plone.form.BaseForm che ci dará la possibilitá di definire esclusivamente un metodo prepare responsabile della configurazione della form:

class MyForm(form.BaseForm):
""" this is a yafowil form
"""

ora definiamo un po' di handlers, metodi indispensabili per la nostra form:

    @property
    def _form_action(self):
        return self.context.absolute_url() + '/' + self.__name__

    def _form_handler(self, widget, data):
        self._do_something(data)

    def prepare(self):
        form = factory('form',
            name='theform',
            props={
                'action': self._form_action,
                'class': 'horizontal'
            })
        form['file'] = factory(
            'field:label:error:file',
            props={
                'label': _(u'File'),
                'field.class': 'field',
        })

        # add submit button
        form['submit'] = factory(
            'field:submit',
            props={
                'label': _(u'Do something'),
                'submit.class': 'myCustomClass',
                'handler': self._form_handler,
        })
        self.form = form

Possiamo avere un handler per bottone, quindi possiamo aggiungere n bottoni nella stessa form, ad esempio:

        form['submit2'] = factory(
            'field:submit',
            props={
                'label': _(u'Do something 2'),
                'submit.class': 'myCustomClass',
                'handler': self._form_handler2,
        })

Gli elementi della form vengono creati usando una catena di blueprint. Prendiamo ad esempio il campo file:

    field:label:error:file

Stiamo dicendo che questo campo deve avere un'etichetta, un box per gli errori ed é di tipo file. Il pacchetto di integrazione in Plone ci dá una shortcut, o meglio una macro, per semplificare questa dichiarazione:

    #field:file

Notare come sia possibile sovrascrivere degli attributi in modo semplice:

    'field.class': 'field',
    'input.class': 'my-input',

ossia: il wrapper del campo avrá la classe CSS 'field' e il campo di input vero e proprio avrá la classe 'my-input'.

E la validazione?

Possiamo definire un validatore in modo molto semplice:

from yafowil.base import ExtractionError

def myvalidator(widget, data):
    if not data.extracted['file']['file'].filename=='foo.txt':
        raise ExtractionError('this field is not valid')
    return data.extracted

quindi modifichiamo il nostra campo cosí:

form['file'] = factory(
    'field:label:error:*myvalidation:file',
    props={
        'field.class': 'field',
        'label': _(u'File'),
    },
    custom={
            'myvalidation': dict(
                extractors=[myvalidator],
            )
    },
)

Usare il form nel template della vista

L'ultima cosa da fare per avere il nostro form, é 'chiamare' il suo renderer nel template della vista:

<div tal:content="structure python:view.render_form()">form</div>

Questo piccolo tour é finito. C'é ancora molto da dire su questa libreria quindi ne parleremo ancora su questo blog. Nel frattempo, se volete saperne di piú, ecco un paio di riferimenti:

Share this on

Share |

On same topics

Commenti

comments powered by Disqus