Personal tools
Sfruttiamo al massimo la Zope Component Architecture

Poche righe, grossi risultati

Sep 18, 2013

Sfruttiamo al massimo la Zope Component Architecture

Utilizziamo la ZCA per aggiungere selettivamente comportamenti basati su eventi, adapter e componenti registrabili in un sitemanager dentro a un sito Plone

Quando aggiungiamo delle funzionalità agli archetypes di un sito Plone tramite la registrazione di utility, adattatori e componenti simili, essi vengono registrati in un site manager.

Tramite questo tipo di componenti possiamo realizzare eventi che, alla creazione o modifica dell'oggetto, eseguono una specifica azione; o adattatori che forniscono comportamenti aggiuntivi a un oggetto, come ad esempio l'aggiunta di campi tramite schemaextender e altre funzionalità simili.

In questo post voglio mostrare come sia possibile associare queste funzionalità aggiuntive ai tipi di contenuto in base alla posizione del sito in cui si trovano. Potremo così avere un tipo di contenuto che in una cartella del sito modifica alcuni suoi dati grazie all'esecuzione di un evento, oppure in altre cartelle potrà generare documenti con campi in più rispetto al documento base, o ancora avere tipi di contenuto che avranno a disposizione delle utility aggiuntive.

Localsitemanager, chi era costui...

Plone, nella sua installazione base, comprende un pacchetto chiamato five.localsitemanager che consente di aggiungere site manager locali alle cartelle del sito; è grazie a questi nuovi site manager che si potranno estendere le funzionalità dei tipi di contenuto già presenti in un sito, senza doverne creare di nuovi.

Supponiamo di avere un sito in cui servono i tipi base di Plone e una sezione particolare in cui si necessita del tipo 'Pagina' con alcune caratteristiche diverse dal tipo originale.

Prima di tutto, è necessario preparare la sezione in cui servono i comportamenti personalizzati, e lo possiamo fare in due modi.

Il primo modo consiste nell'eseguire l'operazione via codice personalizzato e possiamo farlo tramite una vista:


<browser:page
for="*"
class=".create_sm.CreateSM"
name="createsm"
permission="cmf.ManagePortal"
/>

class MakeObjManager(BrowserView): def __call__(self): if not ISite.providedBy(self.context): make_objectmanager_site(self.context)

Una volta preparato il codice, si può chiamare questa vista via browser sulla cartella in cui ci interessa cambiare il comportamento con le funzionalità aggiuntive:


http://www.nomesito.it/cartella/sezione-interessata/@@createsm
 

Così facendo, il contesto su cui si chiama la funzione make_objectmanager_site diventa un site manager locale. Questo metodo può essere comodo se c'è bisogno di effettuare diverse operazioni sulla cartella oltre alla semplice marcatura come nuovo site manager; ad esempio, si potrebbero voler registrare immediatamente degli adattatori o delle utility o altri componenti.

Il secondo metodo lo mette a disposizione five.localsitemanager che registra la vista 'components.html' con un'interfaccia web minimale per marcare e demarcare una cartella come site manager. Anche questa vista sarà richiamabile tramite browser:


http://www.nomesito.it/cartella/sezione-interessata/@@components.html
 

Questo secondo modo è l'ideale se ci interessa semplicemente marcare la cartella come site manager.

Con un nuovo site manager a disposizione, per raggiungere i nostri intenti dobbiamo registrare i nuovi componenti. Non possiamo registrarli via ZCML perché dobbiamo metterli in relazione con il nuovo site manager appena creato, pertanto dobbiamo sfruttare la registrazione tramite python. Supponiamo di voler aggiungere alla pagina un nuovo campo e un evento. Dovremo creare l'adapter e l'handler che ci servono (PageExtender e rename_document):


class ATExtStringField(ExtensionField, atapi.StringField): """ """ class PageExtender(object): """ """ zope.interface.implements(ISchemaExtender) _fields = [ ATExtStringField('productcode', widget=atapi.StringWidget()),
] def __init__(self, context): self.context = context def getFields(self): return self._fields


def rename_document(obj, event):
obj.setTitle('[Prodotto]: %s' % obj.Title()) 

class RegisterAdapters(BrowserView):
def __call__(self):
sm = self.context.getSiteManager()
sm.registerAdapter(
PageExtender,
(IATDocument,),
ISchemaExtender,
name=u'ProductCodePage'
)
sm.registerHandler(rename_document,
(IATDocument, IObjectInitializedEvent))
 

Infine, chiamando la vista RegisterAdapters sulla cartella scelta, rendiamo noto al site manager locale di avere a disposizione queste due funzionalità in più.

Non rimane che testare quanto fatto creando dentro la suddetta cartella una pagina; vedremo che nel form di edit c'è un campo in più (sopra chiamato 'productcode') e che, dopo il salvataggio, il titolo è stato modificato dall'handler che si occupa della gestione dell'evento.

Come controprova è sufficiente creare una pagina fuori dalla suddetta cartella e verificare che i comportamenti descritti qui sopra non si ripetano.

Immagine in testata: http://www.flickr.com/photos/kansasphoto/7871992906/

Immagine per Facebook: http://www.flickr.com/photos/freefoto/5982549938/

comments powered by Disqus