Manual: Zope Page Templates (ZPT) mit ZMS nutzen
Dabei wird im Prinzip ein per Programmcode erzeugtes HTML-Fragment entweder
- als Inhalt in das TAL-attributierte HTML-Element geschrieben (content),
- das attributierte HTML-Element komplett ersetzt oder
- neue Attributwerte für das ausgezeichnete HTML-Element erzeugt
Beispiel:
<title tal:content="context/title">Page Title</title>
Der TAL-Ausdruck liest den Objekt-Titel aus und ersetzt beim Rendering des Templates den bestehenden default-content "Page Title" durch diesen Objekt-Titel.
Der Vorteil des TAL-Ansatzes besteht darin, dass für das Webdesign bestehender HTML-Code als Ganzes verwendet kann (ohne dass eine logische Fragmentierung erforderlich ist). Der HTML-Code wird mit den speziellen Attribute angereichert, damit der Zope-Publisher die Kontext-abhängigen funktionale Erweiterungen des HTML-Codes einsetzen kann („Rendering“). Im Browser kann das „ungerenderte“ Basis-Layout jederzeit kontrolliert und ein gestaltungstechnisches Feintuning durchgeführt werden.
ZMS und TAL
Anstatt der schachtelnden DTML-Mastertemplates standard_html_header und standard_html_footer benötigt das TAL-Konzept nur ein einziges Master-Template: standard_html.
ZMS kann um eine TAL-Editor erweitert werden, der eine interaktive Bearbeitung des Templates „auf dem Content“ erlaubt. Zu diesem Zweck wird unter Konfiguration ->Aktionen die Standard-Aktion editTemplateSet importiert:
ZMS-Aktion editTemplateSet importieren
Die neue Aktion kann dann über die Aktionsliste auf den aktuellen Content-Node angewendet werden. Es erscheint eine framebasierte Vorschau: links die Templates, rechts das Seiten-Rendering. Nach Anklicken eines Templates erscheint dessen Code in einem HTML-Editor.
Template-Editor: Navigation durch die Templates
Template-Editor: Template-Code bearbeiten
ZMS erwartet für das TAL-Publishing das Mastertemplate mit ID standard_html; gleiches gilt nun auch für alle Standard-Templates der (konfigurierten) Contentobjekte. Das Master-Template ordnet Layout-Elemente und Navigations-Funktionalität um den Seitenkern an. Dieser wird über das Standard-Template bodyContentZMSLib_page gerendert und folgendermaßen aufgerufen:
<div id="pagecore" tal:replace="structure context/bodyContentZMSLib_page">
Seiteninhalt
</div>
Seiteninhalt-Redering bodyContentZMSLib_page
<!-- bodyContentZMSLib_page -->
<div id="page">
<tal:block tal:define="global childNodes python:here.getObjChildren('e',request,here.PAGEELEMENTS)">
<tal:block tal:condition="childNodes">
<tal:block tal:repeat="childNode childNodes">
<tal:block tal:content="structure python:unicode(childNode.getBodyContent(request),'utf-8')">
The page-element body-content
</tal:block>
</tal:block>
</tal:block>
</tal:block>
</div>
<!-- /bodyContentZMSLib_page -->
Navigation
<div id="menu" tal:content="structure python:zmsroot.getNavItems(
here,request,{'add_self':False,'deep':False,'complete':False} )"
><ul>
<li><a href="#" title="Item1"><span>Concept</span></a></li>
<li><a href="#" title="Item2"><span>Cases</span></a></li>
<li><a href="#" title="Item3"><span>Download</span></a></li>
<li><a href="#" title="Item4"><span>Academy</span></a></li>
<li><a href="#" title="Item5"><span>Services</span></a></li>
</ul>
</div>
Listen-Iteration ZMS-Datentabelle
Screenshot: Definition der Datentabelle per ZMS-Konfiguration am Beispiel einer Werk-Liste
Screenshot: HTML-Ausgabe der Werk-Liste
TAL-Template für die Iteration der Tabellen-Zellen
Zunächst wird der Datentabelleninhalt ausgelesen und in die globale res Variable geschrieben, Mit tal:repeat="row res" wird über die res-Liste iteriert und den Iterations-Items der Name row gegeben. Auf dieses repeat-Objekt kann per Pfad zugegriffen werden repeat/row und z.B. auf even/odd geprüft werden (also repeat/row/odd).
Per Python-Ausdruck kann der Objektname direkt angesprochen werden, z.B:
tal:content="python: row['year']" und ein Wert aus dem Iterations-Item ausgelesen werden.
<div id="projectlist"
tal:define="global res python:zmscontext.sort_list(zmscontext.projects.attr('records'),
request.get('qorder','year'), qorderdir=request.get('qorderdir','desc'))"
>
<table border="1">
<tal:block tal:repeat="row res">
<tal:block tal:condition="repeat/row/odd">
<tal:block tal:define="global tr_class python:'odd'"></tal:block>
</tal:block>
<tal:block tal:condition="repeat/row/even">
<tal:block tal:define="global tr_class python:'even'"></tal:block>
</tal:block>
<tr tal:attributes="class tr_class">
<td tal:content="python: row['year']">year</td>
<td tal:content="python: row['title']">year</td>
<td tal:content="python: row['type']">year</td>
<td tal:content="python: row['director']">director</td>
<td tal:content="python: row['producer']">producer</td>
<td tal:content="python: row['comment']">comment</td>
</tr>
</tal:block>
</table>
</div>
Erzeugen eines Spalten-Headers mit Item-Links bestehend aus Sortierungs-Parametern:
- qorder für die Variable, nach der die Datensätze sortiert werden sollen
- qorderdir für Richtung der Sortierung (asc vs. desc)
Die URL des Links wird per
tal:attributes erzeugt:
tal:attributes="href python:'?qorder=year&qorderdir=asc'"
Im Detail sieht das TAL-Fragment dann so aus:
qorderdir ist per default
desc, ansonsten alteriert die Sortier-Richtung bei jedem Klick auf den Spalten-Header.
<tr>
<th><a href="?qorder=year"
tal:attributes="href python:'?qorder=year&qorderdir=%s'
%(['asc','desc'][request.get('qorderdir','desc')=='asc'])">Jahr</a></th>
<th><a href="?qorder=title"
tal:attributes="href python:'?qorder=title&qorderdir=%s'
%(['asc','desc'][request.get('qorderdir','desc')=='asc'])">Titel</a></th>
<th><a href="?qorder=type" al:attributes="href python:'?qorder=type&qorderdir=%s'
%(['asc','desc'][request.get('qorderdir','desc')=='asc'])">Kategorie</a></th>
<th><a href="?qorder=director" tal:attributes="href python:'?qorder=director&qorderdir=%s'
%(['asc','desc'][request.get('qorderdir','desc')=='asc'])">Regie</a></th>
<th><a href="?qorder=producer" tal:attributes="href python:'?qorder=producer&qorderdir=%s'
%(['asc','desc'][request.get('qorderdir','desc')=='asc'])">Produktion</a></th>
<th>Anmerkung</th>
</tr>
Python-Scripts als Attribut-Methoden
Um Python-Scripts als Attribut-Methoden verwenden zu können, stellt ZMS das zmscontext-Objekt bereit; diese ist eine ZMS-spezifische Variante des in Python-Scrips überlicherweise eingesetzten context-Objektes und liefert also das kontextuelle ZMS-Objekt.
Beispiel: ZPT-Methode für das Content-Objekt "myteaser" selbst erstellen und bearbeiten.
Der oben stehende Screenshot zeigt den Customteaser myteaser; dieser hat ein titlealt-Attribut, welches der üblicher Teaser-Container im ZMI nicht rendert, weil dieser ein titel-Attribut erwartet. Das Methoden-Attribut title gibt nun einfach das Bestandsattribut titelalt zurück mit
return zmscontext.attr('titlealt')
ZMS lagert die Python-Attributmethode wie üblich in der Objekt-Hierarchie ab:
/content/metaobj_manager/myteaser.title
Mobile-Templates
Zusätzlich zu standard_html kann ein alternatives Mastertemplate mobile_html eingesetzt werden: dieses Mastertemplate rendert automatisch die Dokumente unter einer alternativen URL; während standard_html den Knoten als index_ger.html rendert, erzeugt mobile_html das Dokument unter dem URL mobile_ger.html. Genau wie das Standard-Rendering kann das Mobile-Rendering auch mehrsprachige Dokumente ausgeben.
TAL-Attribute in der Übersicht
-
tal:attributes – setzt HTML-Attribute.
-
tal:block – TAL-Blockelement
-
tal:define – definiert Variablen.
-
tal:condition – prüft Bedingungen.
-
tal:content – ersetzt des Inhalt eines Elements.
-
tal:omit-tag – entfernt das Element und belässt den Inhalt, falls der Ausdruck wahr ist; ansonsten werden tag und content belassen
-
tal:on-error – Fehler-Behandlung
-
tal:repeat – Wiederholt ein Element (List Processing)
-
tal:replace – ersetzt das komplette Element durch den erzeugten Inhalt.
Da diese zusätzlichen Element-Attribute aus einem für den Browser fremden Namespace entstammen (bzw. in der HTML-Spezifikation nicht vorkommen), werden sie vom Browser primär ignoriert. Im Sinne der Code-Vollständigkeit kann man den TAL-Namespace im Root-Element deklarieren:
xmlns:tal=http://xml.zope.org/namespaces/tal
Beispiel: ZMS-Inhalte per TAL auslesen
Der folgende Template-Code zeigt beispielhaft wie auf einem ZMS-Knoten typische Objekte mit dem Einsatz der ZMS-API über Python-Ausdrücke als HTML gerendert werden können, konkret
1. diverse Objekt-Attribute,
2. Node-Content und
3. Child-Nodes
Dieses Zope-Template kann auf jeder ZMS-Ebene aufgerufen werden, z.B.:
http://localhost:8080/myzms/content/e3/testtemplate
Das Bildschirmfoto weiter unten zeigt eine reduzierte Version dieses Beispiel-Codes (ohne Dokumentinhalt):
<html
tal:define="zmsroot here/content;
this here;
charsetter python:request.RESPONSE.setHeader('Content-Type','text/html;; charset=utf-8')">
<head>
<title tal:content="python:zmsroot.attr('title')"></title>
</head>
<body>
<p tal:content="python:this.attr('titlealt')"
style="color:red;font-weight:bold"></p>
<div tal:content="structure python:this.getBodyContent(request)"></div>
<hr />
<h4>filteredChildNodes()</h4>
<ol>
<li tal:repeat="item python:this.filteredChildNodes(request, zmsroot.PAGES)"
tal:attributes="title python:item.attr('title')">
<span tal:replace="python:item.attr('titlealt')">Listitem</span>
</li>
</ol>
</body>
Beachte: Das Element tal:define
kann muliple Variable definieren, die per Semikolon separiert werden; folgt nun ein Semikolon innerhalb einer Variablen-Defintion bzw. soll dieses nicht als delimiter fungieren, so muss dieses doppelt geschrieben werden:
... 'text/html;; charset...
Liste der Unterobjekte per TAL-Code anzeigen
Auswertung der Ausdrücke
Die TAL-Ausdrücke eines HTML-Baumes werden von Zope bzw. TAL-Parser in der Reihenfolge "oben nach unten", also beginnend mit dem root-Element ausgewertet. Sofern mehrere TAL-.Ausdrücke innerhalb eines tags zum Einsatz kommen, kommt folgende Reihenfolge zum Einsatz:
- define
- condition
- repeat
- content oder replace
- attributes
- omit-tag
Der Inhalt des TAL-Ausdrucks kann folgende Typen annehmen:
- path
- python
- string
- nocall
Die Typ-Angabe vor dem Ausdruck (.z.B. path:a/b/c) ist nicht obligatorisch; Zope nimmt per default an, dass es sich um einen Pfad-Ausdruck handelt.
Die Deklaration als nocall-Ausdruck verhindert die Ausführung des Ausdrucks, wie es normalerweise der Fall bei path-Ausdrücken ist; hilfreich ist dies bei der Definition von Variablen:
Beispiele
path
<!-- A. Die URL des aktuellen Web-Requests. -->
<p tal:content="request/URL">URL</p>
<!-- B. Der Login-Name des aktuell angemeldeten Nutzers. -->
<p tal:content="user/getUserName">Username</p>
<!-- C. Liste aller IDs von Objekten im selben Ordner wie Template. -->
<li tal:reapeat="container/objectIds">Liste Item</li>
<!-- D. Context-Attribut ausgeben -->
<h1 tal:content="context/title"> Dokument-Titel </h1>
python
<span tal:content="python: 1 + 2">Resultat</span>
<h1 tal:content="python: context.title">Dokument-Titel</h1>
string
string:Hello, ${user/getUserName}
nocall
<span tal:define="page nocall:context/aPage"
tal:content="string:${page/getId}: ${page/title}">
Id: Title</span>
Wichtige Built-in Names
Einige Namen sind a priori von Zope bereits besetzt und liefern folgende Objekte:
context
– aktuelles Objekt, in dessen Kontext, auf den das Template angewendet wird
zmscontext
– von ZMS bereitgesteller context
container
– Ordner, in dem das Template platziert ist
request
– Zope-REQUEST-Objekt.
repeat
– Item einer sequence-Iteration
default
– Vorgabe-Wert des TAL-Containers
user
– eingeloggter User
nothing
– Nicht-Wert entsprechend Python-None (bzw. void, Nil, NULL).
modules
– Python Module, die zur Nutzung in den Templates freigegeben sind
Erstellt von: Dr. Frank Hoffmann
, Hoffmann+Liebenberg , erstellt am: 14.09.2012
,
zuletzt geändert: 04.02.2014