z3c.form come modificare un widget ed il relativo template per una sola form

z3c.form è un ottimo strumento per creare form in Zope e Plone che, sfruttando i meccanismi della ZCA, ci permette un altissimo livello di personalizzazioni

z3c.form possiede al suo interno già moltissimi widget utilizzabili in diverse situazioni che ci si prospettano davanti ogni giorno.

Purtroppo, nonostante questo, a volte non sono sufficienti a coprire tutti i casi d'uso che ci troviamo di fronte; ecco perché potremmo avere la necessità di registrare nuovi widget piuttosto che modificare il comportamento o il layout di alcuni in determinate situazioni.

Immaginiamo di avere all'interno di z3c.form tutto l'occorrente per la nostra form ma, in un particolare caso il widget fornito per un determinato campo dev'essere leggermente modificato.

Dato che un particolare widget viene discriminato in base a tre elementi:

  • zope.schema.interfaces.IList - discrimina il tipo di campo che abbiamo definito nello schema della form.
  • zope.schema.interfaces.IField - solitamente è fisso su questa interfaccia in quanto è il campo della form definito dall'interfaccia precedente
  • z3c.form.interfaces.IFormLayer - è la request della form che dev'essere passata al widget per associare i valori necessari al widget

in teoria potrei intervenire su uno di questi elementi per registrare un adapter differente che mi permetta di ottenere il widget voluto. Nella pratica il primo ed il secondo elemento sono difficilmente modificabili a meno che non abbiamo bisogno di comportamenti molto complessi.

Possiamo quindi in modo semplice marcare la request della nostra form con un interfaccia particolare in modo tale da ottenere il widget necessario.

Data un interfaccia:

from zope.interface import Interface
class IMyForm(Interface):
    """Marker interface per la mia form
    """

posso registrare un widget particolare nella zcml:

<adapter
factory=".widget.MyWidget"
provides="z3c.form.interfaces.IFieldWidget"
for="zope.schema.interfaces.IList
zope.schema.interfaces.IField
.interfaces.IMyForm"
/>

a questo punto definisco il widget:

class MyWidget(...):
"""Il widget deve ereditare il widget specifico
di cui vogliamo modificare il comportamento """

e le sue specifiche factory che permetteranno a z3c.form di restituire il widget corretto in base ai campi della nostra form (per maggiori informazioni vedi la documentazione ufficiale di z3c.form):

@zope.interface.implementer(interfaces.IFieldWidget)
def myWidgetFactory(field, request):
"""IFieldWidget factory for MyWidget."""
return widget.FieldWidget(field, MultiWidget(request))
@zope.interface.implementer(interfaces.IFieldWidget)
def MyFieldWidget(field, value_type, request):
"""MyWidget"""
return multiFieldWidgetFactory(field, request)

L'ultima cosa che manca ora consiste nel marcare la request della form con la specifica interfaccia per la quale abbiamo registrato il widget:

class MyForm(...):
... def __init__(self, context, request):
...
alsoProvides(request, IMyForm)
...
...

ed il gioco è fatto.

Per trovare ulteriore documentazione potete visitare i seguenti links:

Share this on

Share |

On same topics

Commenti

comments powered by Disqus