Ripasso z3c.form - sovascrivere i widget di default per una sola form

Con z3c.form è possibile creare form complesse in Plone e, una volta compresa a fondo la sua struttura a componenti, consente di personalizzare facilmente ogni singolo aspetto della form.

Tempo fa avevo già scritto qualcosa riguardo alla personalizzazione dei widget di z3c.form. Il tutorial nasceva dall'esigenza di dover modificare un widget per un singolo campo all'interno di una determinata form.

Vorrei ora approfondire la questione riguardo la personalizzazione delle factory dei widget per z3c.form analizzando tre differenti esigenze.

1. Approccio manuale - widgetFactory

Dato il seguente schema:

from zope import schema
from zope.interface import Interface

class IForm(Interface):
my_field = schema.TextLine(
title=u"My Field"
)

z3c.form in automatico associa al field TextLine un semplice widget di tipo 'text'.

Quando definisco la form posso però personalizzare il widget associato a quel  campo sovrascriveno il widgetFactory associato a quel campo in questo modo:

from z3c.form import form, field

class Form(form.Form):
fields = field.Fields(IForm)
fields['my_field'].widgetFactory = MyFieldWidget

2. Usare un'interfaccia per 'differenziare' le form

Qualora abbia più widget dello stesso tipo da associare per alcuni campi della medesima form potrebbe essere più comodo marcare la form con una determinata interfaccia.

In questo modo riuscirò a personalizzare tutti i campi dello stesso tipo con una singola configurazione.

Quindi, data un interfaccia come la seguente:

class IMyCustomForm(Interface):
pass

posso marcare la request della form precedente sostituendomi a z3c.form.interfaces.IFormLayer:

class Form(form.Form):
fields = field.Fields(IForm)

def __init__(self, context, request):
super(Form, self).__init__(context, request)
alsoProvides(request, IMyCustomForm)

ed associare il mio widget personalizzato alla form da zcml:

<adapter
factory=".mywidget.MyFieldWidget"
for="zope.schema.interfaces.ITextLine
.myform.IMyCustomForm"
/>

3. Sovrascrittura di un field

A volte non è possibile intervenire direttamente sulla form e quindi i due esempi precedenti non sono facilmente attuabili.

In altri casi non mi occorre una configurazione specifica per una form ma voglio modificare il comportamento di una serie di field all'interno delle mie form.

Ecco che occorre intervenire più a basso livello: dobbiamo creare un field personalizzato che implementi una certa interfaccia ed associare un widget specifico a tutti i field di quel tipo.

Senza troppa fatica posso sovrascrivere un field di zope.schema:

from zope import schema
from zope.interface import Interface, implements

class IMyCustomField(Interface):
pass

class MyCustomField(schema.TextLine):
implement(IMyCustomField)

e con una configurazione zcml associare a tutti quei field uno specifico widget:

<adapter
factory=".mywidget.MyFieldWidget"
for=".myform.IMyCustomField
z3c.form.interfaces.IFormLayer"
/>

Ulteriori informazioni

Share this on

Share |

On same topics

Commenti

comments powered by Disqus