Si CPS 2 utilisait les macros pour représenter les pages, CPS 3 marque l'arrivée d'une nouvelle approche: les éléments.
A l'usage, l'outil s'utilise comme un dictionnaire. Chaque clé est le nom de l'élement (par convention en majuscule) et la valeur de cette clé est la méthode à appeler dans un contexte précis. Ce contexte étant lui-même un élement.
L'utilisation des éléments se caractérise d'une part par la présence
d'un outil nommé portal_elements
, et d'autre part par
l'utilisation d'un format spécifique pour les méthodes de rendu.
L'utilisation de l'outil portal_elements
en tant que
dictionnaire permet aussi de passer des variables d'une page à l'autre.
Enfin, chaque élément peut se voir attribuer un niveau de cache, de façon à minimiser la quantité de calcul nécessaire au rendu d'une page et l'actualisation du contenu.
portal_elements
dispose de quatre
éléments de base:context
.Il existe aussi deux élements importants mais qu'il faut implémenter, car ce sont justement ceux qui vont nous permettre de personnaliser les pages:
Fort de ces connaissances, nous allons écrire un nouvel élement: PORTAL_URL.
Allez pour cela, avec la ZMI, à la racine d'un site CPS 3
puis dans portal_elements
. En bas se trouve un
formulaire titré Add a new default element.
Remplissons le formulaire:
Nous avons ainsi créé un élément qui est équivalent à:
PORTAL_URL = PORTAL.absolute_url()
À titre d'exercice, créez un element TITLE qui retourne le titre (ou l'id) du contexte. Nous l'utiliserons par la suite.
L'utilisation des éléments met en avant les scripts plutôt que les templates. Créons donc pour commencer une méthode 'index_html.py':
elements = here.portal_elements.getElements(object=context) elements['MAIN'] = "<h2>Bienvenue dans CPS 3</h2> return elements['DISPLAY']
Créons maintenant ce fameux élément DISPLAY
.
Toujours dans portal_elements
, Ajouter
celui-ci:
L'appel à DISPLAY va donc déclencher l'appel à la méthode
element_display
dont voici un exemple de code:
##parameters= elements = context.portal_elements.getElements(object=context) pp = elements['REQUEST'].form.get('pp', 0) if pp: return context.main_printable_display() else: return context.main_browser_display()
Intéressons-nous maintenant à cette méthode 'main_browser_display':
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html tal:define=" elements here/portal_elements/getElements; portal_url elements/PORTAL_URL; title elements/TITLE; "> <head> <title tal:content="title">Titre</title> </head> <body> <h2 tal:content="title">Titre</h2> <div tal:content="structure elements/MAIN"> Contenu de la page </div> </body> </html>
Bien entendu, cette page pourra être plus complexe en faisant appel à des éléments qui calculent des boites ou les balises pour insérer un logo en fonction du contexte (par exemple, un logo par site).
Le code de main_printable_display
est laissé en
exercice.
Il est temps de voir ce que donne cette page en accédant à:
http://serveurzope:port/cps/
Ou son équivalent chez vous :) Bien sûr vous aviez écrit
l'élement TITLE
donné en exercice... ?
Ajoutons une ligne dans index_html.py
pour
avoir un petit aperçu de la puissance des éléments:
elements['TITLE'] = "Bienvenue"
Placez cette ligne juste avant ou après celle qui appelle la
méthode de rendu pour l'élément MAIN
, en tout cas
avant de déclencher le calcul de DISPLAY
.
Rafraîchissez la page de votre navigateur pour voir que le titre est maintenant celui que vous avez placé.
'element_path.py':
##parameters= """ Calcule le chemin d'accès jusqu'au contexte. """ elements = context.portal_elements.getElements() portal = elements['PORTAL'] ppath = portal.getPhysicalPath() l = [] obj = context.this() while obj is not None: try: pp = obj.getPhysicalPath() l.insert(0, obj) if pp == ppath: break obj = obj.getParentNode() except: # XXX Unauthorized continue bc = [] for obj in l: if obj.getProperty('breadcrumb_skip') != 1: if obj is portal: title = 'Accueil' else: title = obj.title_or_id() if title.startswith('L_'): # XXX revisit this when content types are internationalized title = portal.portal_messages(title) url = obj.absolute_url() bc.append({ 'title': title, 'url': url, 'object': obj, }) return bc
'element_breadcrumb.pt':
<div id="breadcrumb" <tal:block define=" elements here/portal_elements/getElements; path elements/PATH" repeat="bc path" <a href="" title="" tal:define=" title bc/title; len_title len(title)" tal:attributes="href string:${bc/url}/; title title" tal:content="python:len_title > 20 and title[:19]+'...' or title"> Lien </a> </tal:block> </div>
Amusez-vous à ajouter ce breadcrumb à
main_browser_display
...
Regardons maintenant la méthode de vue d'un objet
MailingList?. L'action view du portal type a
été mis à mailinglist_view
. Voici son code:
##parameters= elements = context.portal_elements.getElements(object=context) elements['CURRENT_ACTION'] = 'view' elements['MAIN'] = context.mailinglist_view_template() return elements['DISPLAY']
L'ancienne méthode de vue a été renommée
mailinglist_view_template.pt
et doit donc être
appelée par ce script. Voici un apercu de son code:
<tal:block define=" elements here/portal_elements/getElements; current_action elements/CURRENT_ACTION; yes string:L_mailinglist oui; no string:L_mailinglist non; doc here/getContent; "> [...] Ici le code fonctionne comme avant... sauf l'appel aux macros bien sûr. [...] </tal:block>
To be continued...
*Hervé Cauwelier*