Personal tools
You are here: Home Plone Book 5. Einführung in einfaches Plone-Templating
Die maximale Bildbreite kann wie folgt gewählt werden:

5. Einführung in einfaches Plone-Templating

Document Actions

Einführung in einfaches Plone-Templating

Plone kombiniert drei Technologien bei der Erstellung einer Webseite. Python und Seiten-Templates erzeugen HTML, das an den Browser gesendet wird. Dort wird mit einigen CSS-Stylesheets die hübsche Seite dargestellt, mit der Sie nunmehr vertraut sind. In diesem Kapitel und in Kapitel 6 stellen die beiden ersten Elemente, der Python-Code und die Seiten-Templates, den Hauptgegenstand der Betrachtung dar.

Um zu verstehen, wie man ein Plone-Template erzeugt und bearbeitet, muss man zunächst einiges über die wesentlichen zugrunde liegenden Konzepte lernen. Manche davon sind für Plone besonders einmalig, und obwohl sie große Vorteile haben, braucht man einige Zeit, um sich daran zu gewöhnen.

In diesem Kapitel beginne ich damit, dass ich das Objekt-Publishing behandle. Ich erkläre, wie man mit Objekten innerhalb von Plone interagiert. Danach erkläre ich, wie man Ausdrücke zusammensetzt. Sobald Sie mit diesen beiden Konzepten vertraut sind, beschreibe ich, wie Plone-Seiten wirklich zusammengestellt werden. Am Ende dieses Kapitels werden Sie eine neue Seite in Ihrer Plone-Site erstellen, die jene Techniken verwendet, die Sie bislang kennen gelernt haben.

Dieses Kapitel macht etwas mehr Sinn, wenn Sie mit Python schon etwas vertrauter sind. Ich werde aber durchgehend das Konzept hinter dem Code erklären, d.h., auch wenn Sie kein Python verstehen, sollten Sie damit zurechtkommen. Der Rest des Buchs verweist auf TALES- (Template Attribute Language Expression Syntax) und Script(Python)-Objekte, d.h., Sie sollten sich in diesem Kapitel die Zeit nehmen, sich mit ihnen vertraut zu machen. Aber Sie sollten bereits einen guten Start haben: TALES habe ich schon im vorigen Kapitel eingeführt, weil es bei der Erzeugung von Portlets und Aktionen benutzt wird.

Die zugrunde liegende Templating-Maschinerie

Ein direktes Eintauchen in die Arbeitsweise von Plone-Templates würde Sie vermutlich ein wenig verwirren, daher gehe ich erst einmal die Templating-Maschinerie durch, auf der sie aufbauen. Idealerweise wäre das etwas, worüber Sie sich keine Sorgen machen müssten, aber in der Praxis habe ich festgestellt, dass es die erste Hürde ist, über die man stolpert, wenn man anfängt, Plone zu benutzen.

Plone ist insofern einmalig, als alles in Plone ein Objekt ist. Seien Sie beruhigt, wenn Sie mit dem Konzept von Objekten nicht so recht vertraut sind. Es steckt nicht viel dahinter: Ein Objekt ist einfach ein Ding, das ein bestimmtes Verhalten hat. Jedes Objekt verfügt über Methoden, die Sie aufrufen können. Eine Computer-Maus könnte beispielsweise Methoden namens bewegen, klicken und rechtsklicken haben.

Ein Dokument in Plone ist ein Objekt eines bestimmten Typs. Das heißt nichts weiter, als dass das Dokument nicht einfach nur aus statischem Text besteht, sondern ein bisschen komplizierter und weitaus nützlicher ist. In Plone hat ein Dokument z.B. eine Methode namens description, die Ihnen eine Beschreibung liefert, die der Benutzer hinzugefügt hat. Bei der Benutzung des Templating-Systems werden Sie sehen, dass alles ein Objekt ist. Zuerst werden Sie aber ein paar Grundprinzipien beim Objekt-Publishing kennen lernen.

Einführung in das Objekt-Publishing

In Plone veröffentlichen Sie eigentlich Objekte, die sich in Zope befinden. Die meisten davon sind Objekte, die persistent in der Objektdatenbank gespeichert sind. Das Konzept ist komplizierter als bei den üblichen CGI-Umgebungen (Common Gateway Interface), in denen Sie ein Script ausführen und ihm eine Reihe von Anfragevariablen übergeben. In Plone ist alles ein Objekt, in Zope ist alles ein Objekt, und auch in Python ist alles ein Objekt. Bis jetzt habe ich es vermieden, das Wort Objekt zu verwenden, und habe stattdessen Wörter wie Template, Script und Eintrag benutzt, aber all das sind wirklich Objekte, die sich lediglich unterschiedlich verhalten.

Wenn Sie von Plone einen URL (Uniform Resource Locator) abfragen, wird ein Objekt aus der Umgebung aufgerufen. Das macht Plone so, dass es den URL in einen Pfad übersetzt. Das heißt: Falls der URL /Plone/login_form lautet, versucht Plone, aus diesem URL einen Pfad zu bestimmen und all die Objekte darauf in der Datenbank zu finden. Dabei findet es das Objekt Plone und darin dann ein Objekt login_form. Dieses Absuchen des Pfads wird auch Traversierung genannt. Im Grunde genommen traversiert Zope diese Objekte und ruft das letzte Objekt im Pfad auf.

Wenn Zope das Objekt login_form aufruft, wird dieses Objekt in seinem Kontext ausgeführt. Den Begriff Kontext werden Sie im Zusammenhang mit Plone oft hören. Es ist lediglich der aktuelle Kontext des ausgeführten Objekts. In diesem Fall ist es /Plone. Der Kontext verändert sich ständig, während Sie sich in einer Plone-Site bewegen. Falls Sie den URL /Plone/Members/login_form in einem Browser aufgerufen haben, wäre der Kontext /Plone/Members.

Wie oben erwähnt wurde, können Sie per Traversierung mit Hilfe eines Programms genauso auf Objekte in Plone zugreifen, wie Sie es mit einem URL tun. Das ähnelt dem Zugriff auf Dateien in einem Dateisystem. Das heißt: Wenn Sie unter Windows auf ein Bild in Eigene Dateien zugreifen möchten, würden Sie ein Verzeichnis eingeben wie C:\Dokumente und Einstellungen\andym\Eigene Dateien\Mein Portrait.jpg. Auf ein Objekt in Plone könnten Sie zugreifen, indem Sie Members/andy/Mein Portrait.jpg eingeben. Das würde auch funktionieren, sofern Sie eine Reihe von Ordnern und Objekten wie folgt hätten:

Members
  |_ andy
     |_  Mein Portrait.jpg

In der Dateisystemversion gehen Sie auf der Festplatte des Rechners Verzeichnis für Verzeichnis durch. In Plone geschieht das Gleiche, nur ist es so, dass Members und andy Objekte sind.

Ein Unterschied besteht darin, dass Zope die Schreibweise beachtet. Unter Windows können Sie Mein Portrait.jpg oder mein portrait.jpg eingeben. In Plone wird das aber nicht funktionieren, denn Sie müssen die gleiche Schreibweise wie in der Objekt-ID verwenden. Aus diesem Grund empfiehlt es sich, in allen URLs Kleinbuchstaben zu verwenden, damit Ihre Benutzer weniger Fehler machen können.

Plone und Zope haben eine Besonderheit namens Akquisition zu diesem Publishing-System hinzugefügt. Das Konzept dahinter ist das des Enthaltenseins: Objekte befinden sich in anderen Objekten, die als Container bezeichnet werden. Im vorigen Beispiel ist das Objekt andy ein Container innerhalb des Members-Containers innerhalb des Plone-Site-Containers (der sich seinerseits innerhalb des Zope-Application-Containers befindet).

In einer normalen objektorientierten Umgebung erbt ein Objekt Verhalten von seinem Elternobjekt. In Plone und Zope erbt ein Objekt auch Verhalten von seinem Container. Dabei wandert ein Objekt durch eine Container-Hierarchie, um herauszufinden, wo es dieses Verhalten findet.

Nehmen Sie z.B. den Zugriff auf Members/andy/Mein Portrait.jpg. Was geschähe, wenn das Objekt Ein Bild.jpg nicht im Ordner andy vorhanden wäre, sondern weiter oben in der Hierarchie? Nun, dank Akquisition würde es für Sie gefunden. Betrachten Sie die folgende Hierarchie:

Members
   |_ andy
   |_ Mein Portrait.jpg

In diesem Fall würde Plone, wenn Sie die URL ausführen, diese bis andy traversieren und dann versuchen, dort Mein Portrait.jpg zu finden, was aber in dem Container nicht existiert. Daher würde es in der Container-Hierarchie suchen, also im Ordner Members, wo es Mein Portrait.jpg findet und zurückgibt. Als Ergebnis sieht der Benutzer das Bild wie sonst auch.

Wenn Sie das jedoch mit dem vorigen Beispiel vergleichen, in dem das Bild im Ordner andy enthalten war, würden Sie folgende Unterschiede feststellen:

  • Erstens ist der Kontext der gleiche, auch wenn sich das Objekt an einem anderen Ort befindet. Der Kontext basiert auf dem Ort, von dem aus das Objekt aufgerufen wird.
  • Zweitens ist der Container ein anderer, und der Container von Mein Portrait.jpg ist nun ein anderer, nämlich Members und nicht andy.

Worauf will ich also hinaus? Nun, jetzt können Sie ein Objekt in die Wurzel einer Plone-Site setzen, und ein beliebiges anderes Objekt kann darauf zugreifen, weil ersteres mit Hilfe der Akquisition gefunden wird.

Auch wenn das alles vermutlich Sinn macht, sollten Sie wissen, dass Akquisition ziemlich kompliziert werden kann, besonders bei der Suche in der Kontexthierarchie (die vorkommen kann). Wenn Sie gern mehr darüber lernen möchten, können Sie eine hervorragende Abhandlung zum Thema Akquisition von Jim Fulton, dem Systemarchitekten von Zope, unter http://www.zope.org/Members/jim/Info/IPC8/AcquisitionAlgebra/index.html lesen.

Einführung in Template-Ausdrücke

Bevor Sie ins Zope Page Templates-System eintauchen, müssen Sie TALES verstehen. Oft müssen Sie in einer Anwendung Ausdrücke schreiben, die dynamisch ausgewertet werden können. Das sind keine Scripts, sondern einzeilige einfache Ausdrücke, die etwas Einfaches mit einer Zeile Code machen können.

Ein Ausdruck wird mit einer Reihe von lokalen Variablen ausgewertet, die an ihn übergeben werden. Diese Variablen werden durch das bestimmt, was den Ausdruck aufruft. Vom Workflow wird eine Reihe Variablen übergeben, und das Zope Page Templates-System übergibt eine Reihe weiterer. Vorläufig werde ich Beispiele verwenden, die einen context haben. Wie Sie sich hoffentlich erinnern, ist context der Kontext, in dem ein Objekt aufgerufen wird.

Bislang haben Sie schon einige TALES-Ausdrücke wie string:${portal_url}/Software gesehen. Dies ist aber nur ein Beispiel aus einem weiten Spektrum möglicher Ausdrücke. Die Hauptanwendung von TALES liegt bei den Zope Page Templates, dem System, mit dem Plone HTML generiert. Auch wenn der Name vermuten lässt, dass es nur in Templates zu gebrauchen ist, verwenden viele Werkzeuge in Plone diese Syntax bei einfachen Ausdrücken, z.B. Aktionen, Workflow und Sicherheit. Es gibt verschiedene Arten von Ausdrücken, die ich einzeln durchgehen werde.

Pfadausdrücke verwenden

Der Pfadausdruck ist der Standardausdruck, der auch am meisten verwendet wird. Anders als alle anderen Ausdrücke benötigt er kein Präfix, um den Typ des Ausdrucks anzugeben. Der Ausdruck umfasst einen oder mehrere Pfade. Die Pfade sind mit einem senkrechten Strich (|) voneinander getrennt. Jeder Pfad besteht aus einer Reihe von Variablen, die mit Schrägstrichen (/) voneinander getrennt sind. Hier sind einige einfache Beispiele:

context/message
context/ordnerA/title
context/Members/andy/Mein Portrait.jpg

Bei der Auswertung des Ausdrucks wird der Pfad an den Schrägstrichen aufgeteilt. Dann wird ausgehend vom linken Wert versucht, das Objekt, die Methode oder den Wert zu finden. Dieses Objekt wird dann auf den aktuellen Stack gelegt, und es geht mit dem nächsten Wert weiter. Das wird so lange wiederholt, bis das Ende des Ausdrucks erreicht ist oder kein passender Wert gefunden wird. Falls das gefundene Objekt ein Python-Dictionary oder ein Abbildungsobjekt ist, wird dieser Wert des Dictionarys aufgerufen. Eine nette Eigenschaft von Pfadausdrücken ist, dass / das einzige reservierte Zeichen ist. Das heißt, Namen dürfen Leerzeichen und Punkte enthalten und können dennoch ausgewertet werden.

Wenn das Ende erreicht ist, wird dieses Objekt aufgerufen, sofern das möglich ist. Handelt es sich um ein nicht aufrufbares Objekt, wird der String-Wert des Objekts geholt und zurückgegeben. Falls bei dieser Suche zu irgendeinem Zeitpunkt ein Fehler auftritt (am häufigsten passiert es, dass das verlangte Attribut nicht existiert), wird mit dem nächsten Alternativausdruck weitergemacht, sofern einer vorhanden ist. Einen Alternativausdruck können Sie nach einem senkrechten Strich angeben.

Beispiel:

context/ordnerA/title|context/ordnerB/title

Im vorigen Beispiel wird der Titel von ordnerA ausgegeben, wenn er existiert, oder der Titel von ordnerB, falls der erste nicht existiert. Dieser Vorgang wird für jeden Ausdruck so lange wiederholt, bis es keine weiteren Ausdrücke gibt oder einer davon erfolgreich ausgewertet werden kann.

Not-Ausdrücke verwenden

Ein negierter Ausdruck hat das Präfix not: und invertiert einfach die Auswertung des TALES-Ausdrucks, der dem Präfix folgt. Da das Zope Page Templates-System keine if-Anweisung kennt, können Sie hiermit das Gegenteil einer vorherigen Bedingung testen.

Beispiel:

not: context/message|nothing
Nocall-Ausdrücke verwenden

Wenn ein Pfadausdruck das letzte Element im Pfad erreicht, wird dieses, wenn möglich, standardmäßig aufgerufen. Das Präfix nocall: verhindert genau das. Ein Nocall-Ausdruck wird in Plone selten verwendet, hat aber gelegentlich seinen Zweck. Sie können ihn z.B. dafür benutzen, auf ein anderes Objekt zu verweisen, es aber nicht auszugeben.

Beispiel:

nocall: context/einBild
String-Ausdrücke verwenden

Mit String-Ausdrücken können Sie Text und Variablen in einem Ausdruck mischen. Alle String-Ausdrücke beginnen mit dem Präfix string:. Dies ist eine nützliche und recht häufig benutzte Funktion. Der Text darf alles enthalten, was in einem Attribut erlaubt ist, d.h. im Wesentlichen alphanumerische Zeichen und Leerzeichen. In Text können Variablen enthalten sein, denen ein Dollar-Zeichen ($) vorangestellt sein muss. Hier einige Beispiele:

string: Dies ist ein langer String
string: Dies ist der $title

Im letzten Beispiel wird die Variable $title ausgewertet. Die Variable kann ein beliebiger Pfadausdruck sein. Wenn sie / enthält, muss die Variable in {} verpackt werden, um den Anfang und das Ende des Ausdrucks deutlich zu machen.

Beispiel:

string: Dies ist der ${context/einBild/title}.

Falls ein Dollar-Zeichen im Text geschützt werden muss, setzen Sie ein weiteres Dollar-Zeichen vor das zu schützende Dollar-Zeichen.

Beispiel:

string: In $$US kostet es ${context/meinDing/kosten}.
Python-Ausdrücke verwenden

Python-Ausdrücke werten eine Zeile Python-Code aus. Alle Python-Ausdrücke beginnen mit dem Präfix python: und enthalten eine Zeile Python-Code.

Beispiel:

python: 1 + 2

Der Python-Code wird unter dem gleichen Sicherheitsmodell ausgewertet, das auch ein Script(Python)-Objekt benutzt, wie in Kapitel 6 dargestellt wird. Aus diesen Gründen sollte der Python-Code einfach und auf Präsentationsfunktionen beschränkt sein, z.B. auf die Formatierung von Strings und Zahlen oder auf das Aufstellen einfacher Bedingungen.

Weiterhin gilt, dass fast alle anderen erwähnten TALES-Ausdrücke in Python verpackt und aufgerufen werden können. Folgendes sind die entsprechenden Ausdrücke:

  • path(string): Wertet einen Pfadausdruck aus.
  • string(string): Wertet einen String-Ausdruck aus.
  • exists(string): Wertet einen String-Ausdruck aus.
  • nocall(string): Wertet einen Nocall-Ausdruck aus.

Beispielsweise ist folgender Code:

python: path('context/Members')

äquivalent zu folgendem:

context/Members

Einige Funktionen wurden auch hinzugefügt, um Entwicklern ihre Arbeit bequemer zu machen. Die Funktion test erwartet drei Parameter: eine auszuwertende Anweisung und die Bedingungen für true und false. Die Anweisung wird ausgewertet, und es wird der entsprechende Wert zurückgegeben.

Beispiel:

python: test(1 - 1, 0, 1)

Die Funktion same_type erwartet zwei Parameter und stellt fest, ob sie gleich sind. Beispiel:

python: same_type(irgendwas, '')

Manche Entwickler raten davon ab, Python-Code im Zope Page Templates-System zu benutzen, weil das bedeutet, dass Logik zu den Präsentations-Templates hinzugefügt wird. Für Entwickler ist es oftmals hilfreich, sich bei jedem hinzugefügten Python-Happen zu fragen, ob dieser Code nicht besser ausgegliedert und in ein separates Script(Python)-Objekt verlagert werden sollte. Das heißt nicht, dass Sie jedes Stück Python-Code ausgliedern sollen, sondern nur, dass Sie darüber nachdenken sollten, bevor Sie etwas hinzufügen.

Das Zope-Page Templates System verwenden

Nun da Sie das Object-Publishing und Ausdrücke verstehen, können Sie sich aufs Eingemachte im System stürzen, auf Zope Page Templates. Das ist das Templating-System, mit dem Plone HTML generiert.

Es sind sehr viele Systeme zum Generieren von HTML verfügbar, und zu den bekannteren gehören JavaServer Pages, Active Server Pages und PHP. Den Benutzern dieser anderen Systeme sei gesagt: Das Zope Page Templates-System sieht zu Beginn sehr merkwürdig aus, aber Sie werden schnell sehen, dass es ein sehr mächtiges System ist.

Das einfachste Template sieht ungefähr wie folgt aus:

<p tal:content="here/message">Der Titel</p>

Wenn der Wert von message gleich Hello, World! wäre, dann wäre Folgendes eine Ausgabe bei der Darstellung des Templates:

<p>Hello, World!</p>

Im Moment überspringe ich einige der Feinheiten und zeige, was hier passiert ist. Ein normaler Absatz wurde in HTML geschrieben, aber der Inhalt dieses Absatzes ist nicht der Text, der in der Ausgabe gezeigt wird. Zu dem öffnenden Tag des Absatzes wurde das Attribut tal:content hinzugefügt, und der Ausdruck here/message wurde diesem Attribut zugewiesen. Als Absatzinhalt wurde aber der Wert der Variablen message ausgegeben (in diesem Fall, Hello, World!).

Das Template wird zur Laufzeit ausgewertet, und das Attribut tal:content wird aufgerufen. Der tal-Teil steht für Template Attribute Language, eine Sprache, die eine Reihe von Befehlen enthält, z.B. content. All diese Befehle werden Sie später noch sehen. Mit ihnen können Sie fast alles tun, was Sie mit HTML-Tags tun möchten. Sie können Schleifen erzeugen, Tags ändern, Attribute ändern, Tags entfernen usw. Bevor das Template ausgeführt wird, wird es als gültiges XHTML (Extensible HTML) angezeigt und wird in einem Editor als Absatz mit diesem Text angezeigt.

All diese Page Templates sind gültiges XHTML. XHTML ist ein Standard für HTML und ist gültiger XML-Code (Extensible Markup Language). Das bedeutet, Sie müssen sich an folgende Regeln halten:

  • Alle Tags müssen in Kleinbuchstaben geschrieben sein.
  • Attribute müssen immer in Anführungszeichen stehen (z.B. <input type="checkbox" checked="1" />).
  • Leere Elemente müssen terminiert werden (z.B. <br />, nicht <br>).

Um eine Seite als XHTML zu definieren, müssen Sie eine DOCTYPE-Deklaration angeben und den XML-Namespace benutzen, der im html-Tag gesetzt ist. Plone verwendet folgende Deklaration oben auf jeder Seite:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

Weitere Informationen zur XHTML-Spezifikation finden Sie unter http://www.w3.org/TR/xhtml1/#xhtml.

Einführung in Page Templates und Inhalt

Wie Sie nun wissen, ist Plone ein Content-Management-System, bei dem Benutzer über das Web Inhalte zur Plone-Site hinzufügen können. Diese Inhaltsobjekte werden innerhalb von Plone gespeichert und dann mit Hilfe von Page Templates für alle Welt dargestellt.

Kommen wir zum früheren Beispiel des Zugriffs auf /Members/andy/Mein Portrait.jpg zurück. Ich werde nun beschreiben, was mit dem Inhalt in Plone wirklich passiert. Zuerst findet Plone das Objekt Mein Portrait.jpg und ruft es auf. Es wird deswegen aufgerufen, weil keine spezielle Methode auf dem Objekt aufgerufen wird. Wenn ein Inhaltstyp aufgerufen wird, wird ein bestimmtes Template gefunden und dargestellt. Der Kontext für dieses Template wird das Bild sein, auf das Sie zugreifen möchten, und das Template ist jenes für dieses Bild.

Wenn eine andere Aktion auf dem Bild aufgerufen würde, z.B. /Members/andy/Mein Portrait/image_edit, dann würde die Aktion image_edit für dieses Objekt gesucht, und das entsprechende Template würde zurückgegeben werden. Wie das funktioniert, beschreibe ich in Kapitel 11 im Detail.

In allen Templates in Plone werden Sie also eine Referenz zu here oder context sehen. Das ist der Kontext des Inhalts, auf den zugegriffen wird. In einem Template können Sie nun context/irgendwas oder wasanderes schreiben, und das wird das irgendwas oder wasanderes sein, das relativ zu dem Stück Inhalt und nicht zum Template gesucht wird. Jetzt werden Sie Ihr erstes Template in Plone erstellen.

Erstellen Ihres ersten Page Templates

Die Standardmethode, ein Page Template zu erstellen, ist das Zope Management Interface (ZMI). Weil das bedeutet, das Template im Textbereich eines Webbrowsers zu bearbeiten, ist das ZMI leider auch die unangenehmste Methode, die man als Entwickler benutzen kann. Verglichen mit den meisten Editoren, bietet dieser Textbereich sehr wenige Funktionen. Es fehlen Eigenschaften wie Zeilennummern, Syntax-Hervorhebung usw. In Kapitel 9 zeige ich Ihnen, wie Sie mit dem External Editor Inhalte bearbeiten können. Damit können Sie den Inhalt der Website in lokalen Editoren wie Macromedia Dreamweaver oder Emacs bearbeiten. In Kapitel 6 zeige ich Ihnen, wie Sie Plone dazu bringen, Page Templates als Dateien von der Festplatte zu lesen, und dann können Sie ein beliebiges Werkzeug dafür benutzen.

Um ein Template zu erstellen, gehen Sie ins ZMI, klicken erst auf portal_skins, dann auf custom und wählen dann Page Template im Dropdown-Menü (siehe Abbildung 5.1). Klicken Sie auf Add, und anschließend sehen Sie die Seite in Abbildung 5.2.

img/05-01.png

Abbildung 5.1. Wählen der Page Template-Option

img/05-02.png

Abbildung 5.2. Hinzufügen eines Page Templates

Geben Sie test als ID des Page Templates ein. Klicken Sie dann auf Add und auf den Edit-Button, mit dem Sie zum Management-Schirm gelangen (siehe Abbildung 5.3). Dann können Sie dieses Template über das Web bearbeiten, indem Sie den Textbereich benutzen und auf Save Changes klicken, um die Änderungen zu speichern.

img/05-03.png

Abbildung 5.3. Bearbeiten eines Page Templates

Hinweis

Vor Zope 2.7 durchliefen alle Page Templates die Variable here, die äquivalent zu context ist. Wenn Sie here in irgendeinem Stück Code in einem Page Template sehen, bedeutet das context. Die neue Variable context wurde hinzugefügt, um klarer zu sein und die Page Templates mit Script(Python)-Objekten zu harmonisieren.

Nach einem Klick auf Save Changes wird das Page Template kompiliert. Falls Sie Fehler im Template gemacht haben sollten, sehen Sie diese oben auf der Seite hervorgehoben. Abbildung 5.4 zeigt einen Fehler bei einem h1-Tag an, das nicht geschlossen ist. (Wie zuvor erwähnt wurde, müssen Page Templates gültiges XHTML sein.)

img/05-04.png

Abbildung 5.4. Page Template-Fehler

Nachdem Sie das Page Template erfolgreich gespeichert haben, können Sie auf den Test-Reiter klicken, um den dargestellten Wert des Templates zu sehen. In Abbildung 5.5 sehen Sie, dass die Überschrift durch die ID des Templates ersetzt wurde und dass der Hauptabsatz nun die ID des Templates enthält.

img/05-05.png

Abbildung 5.5. Erzeugen der Seite

Der Management-Bildschirm eines Page Templates enthält auch die folgenden wichtigen Eigenschaften:

  • Title: Dies ist der Titel dieses Templates, der optional ist. Wenn Sie diesen im vorigen Beispiel ändern, z.B. nachdem Sie auf Test geklickt haben, werden Sie feststellen, dass sich das HTML im Ergebnis verändert hat.
  • Content-Type: Dies ist der Inhaltstyp dieses Templates, der normalerweise text/html ist.
  • Browse HTML source: Hiermit wird das Template als unverarbeitetes HTML dargestellt. So würde das Template erscheinen, wenn es in einem HTML-Editor geladen würde.
  • Test: Hiermit wird das Template verarbeitet und dargestellt.
  • Expand macros when editing: Bei angekreuztem Kontrollkästchen wird versucht, Makros zu expandieren. Ich empfehle, es meistens nicht angekreuzt zu lassen. Makros sind eine Eigenschaft für Fortgeschrittene und werden in Kapitel 6 behandelt.

Nun, da Sie ein Page Template erzeugt haben, werden Sie ein paar Änderungen daran vornehmen. Dabei werden die Themen demonstriert, die bisher in diesem Kapitel behandelt worden sind. Wenn Sie z.B. möchten, dass Ihr Page Template 1+2 berechnet, könnten Sie folgende Zeile zu Ihrem Page Template hinzufügen:

<p>1+2 = <em tal:content="python: 1+2" /></p>

Klicken Sie dann auf den Test-Reiter, um zu sehen, ob es funktioniert. Sie sollten Folgendes sehen:

1+2 = *3*

Um ein Beispiel für eine Pfadtraversierung zu sehen, geben Sie das Logo Ihrer Plone-Site aus. Sie können einen Ausdruck im Logo Ihrer Plone-Site einfügen, indem Sie Folgendes zu Ihrem Page Template hinzufügen:

<p tal:replace="structure context/logo.jpg" />

Hierdurch wird das passende HTML für das Bild erzeugt und auf der Seite angezeigt.

Die Grundsyntax von Page Templates

Nachdem Sie nun gesehen haben, wie man ein Page Template erstellt, werde ich dessen grundlegende Syntax erklären. Die Syntax von Page Templates lässt sich in einige verschiedene Bestandteile gliedern, die ich in den folgenden Abschnitten behandeln werde.

Einführung in eingebaute Variablen

Die Syntax von Ausdrücken kennen Sie bereits, also werden Sie nun Variablen kennen lernen, die Ausdrücken übergeben werden, wenn Sie ein Page Template darstellen. Alles nun Folgende spielt sich im Kontext eines Zugriffs auf das Bild Ein Bild.jpg im Ordner Members/andy mit dem URL /Members/andy/Ein Bild.jpg ab:

  • container: Dies ist der Container, in dem sich das Template befindet. Bei Plone ist das normalerweise der Ordner portal_skins. Sie sollten es vermeiden, einen Container zu verwenden, weil portal_skins unerwartete Änderungen am Container bewirken kann (z.B. eine Referenz auf den Ordner andy).
  • context: Dies ist der Kontext, in dem das Template ausgeführt wird. In Plone ist das das angezeigte Objekt, falls Sie ein Portalobjekt anzeigen (z.B. eine Referenz auf das Objekt Ein Bild.jpg).
  • default: Manche Anweisungen haben ein spezielles Standardverhalten. Darauf wird bei allen Anweisungen hingewiesen, und diese Variable ist ein Zeiger auf dieses Verhalten.
  • here: Dies ist äquivalent zu context.
  • loop: Dies ist äquivalent zu repeat.
  • modules: Dies ist ein Container für importierte Module. So ist z.B. modules/string/atoi die Funktion atoi aus Pythons string-Modul. Hierunter fallen alle Module, die man gefahrlos ins Zope Page Templates-System importieren kann. Weitere Informationen finden Sie im Abschnitt "Plone mit Python scripten" in Kapitel 6.
  • nothing: Dies ist das Äquivalent zu None in Python.
  • options: Dies sind die Optionen, die ans Template übergeben werden, was dann passiert, wenn das Template von einem Script oder einer anderen Methode und nicht über das Web aufgerufen wird.
  • repeat: Dies ist das wiederholte Element (siehe das Element tal:repeat im Abschnitt "Einführung in die Syntax von TAL-Anweisungen" in diesem Kapitel).
  • request: Dies ist die eingehende Anfrage des Clients (alle Werte der eingehenden Anfrage sind mit Hilfe des folgenden Kontext-Testscripts sichtbar). Alle GET- und POST-Parameter werden zwecks leichteren Zugriffs mit dem Python-Modul marshall in ein Dictionary serialisiert. Hier sind einige Beispiele:
request/HTTP_USER_AGENT # der Browser des Benutzers
request/REMOTE_ADDRR  # der Browser des Benutzers
request/someMessage   # der Wert einer Meldung im Abfrage-String
  • root: Dies ist das Zope-Wurzelobjekt. Mit root/Control_Panel erhalten Sie beispielsweise das Control Panel für Zope.
  • template: Dies ist das aufgerufene Template. Mit template/id erhalten Sie z.B. die ID des dargestellten Templates.
  • traverse_subpath: Dies enthält eine Liste von Elementen, die noch traversiert werden müssen. Es handelt sich um eine Variable für Fortgeschrittene, die Sie besser erst dann verwenden sollten, wenn Sie Traversierung und Akquisition verstanden haben.
  • user: Dies ist das aktuelle Benutzerobjekt. user/getUserName ist der Benutzername des aktuellen Benutzers.
  • CONTEXTS: Dies ist eine Liste mit den meisten dieser Werte.

Hinweis

Mit Ausnahme von CONTEXTS können all diese Variablen in einer tal:define-Anweisung neu definiert werden, wenn der Benutzer das möchte. Das ist allerdings nicht ratsam, weil das für jemanden, der den Code verwendet, recht verwirrend sein kann.

Das Page Template test_context zeigt die Werte all dieser Variablen sowie den Ort einiger Objekte (siehe Listing 5.1). Es kann hilfreich bei der Fehlersuche und beim Bestimmen von Variablenwerten sein. Fügen Sie es als Page Template namens test_context hinzu, und klicken Sie dann auf Test, um die Ergebnisse zu sehen.

Listing 5.1. test_context

<html>
  <head />
  <body>
    <h1>Debug information</h1>
  <h2>CONTEXTS</h2>
  <ul>
    <tal:block
        tal:repeat="item CONTEXTS">
    <li
        tal:condition="python: item != 'request'"
        tal:define="context CONTEXTS;">
            <b tal:content="item" />
            <span tal:replace="python: context[item]" />
    </li>
    </tal:block>
  </ul>
  <h2>REQUEST</h2>
  <p tal:replace="structure request" />
  </body>
</html>

Das Page Template test_context produziert die Ausgabe, die Sie in Abbildung 5.6 sehen.

img/05-06.png

Abbildung 5.6. Ein Beispiel für alle Standardvariablen in einem Script

Einführung in die Syntax von TAL-Anweisungen

Die Sprache TAL (Template Attribute Language) bietet alle grundlegenden Bausteine für eine dynamische Präsentation. TAL definiert acht Anweisungen: attributes, condition, content, define, omit-tag, on-error, repeat und replace.

Da Page Templates gültiges XML sind, müssen alle TAL-Attribute in Kleinbuchstaben geschrieben werden. Außerdem darf jedes Element eine Anweisung nur einmal enthalten. In den folgenden Beispielen habe ich in den Elementen Zeilenumbrüche eingefügt, um die Lesbarkeit zu verbessern. Das ist absolut gültiger Code und kommt recht häufig im Plone-Quellcode vor. Dennoch ist es optional und wird nicht verlangt.

tal:attributes: Element-Attribute ändern

Mit tal:attributes können Sie ein oder mehrere Attribute eines Elements ersetzen. Eine Anweisung enthält die zu ändernden Attribute, die mit einem Leerzeichen von der Anweisung getrennt werden. Beispiel:

<a href="#"
   tal:attributes="href context/absolute_url">
   Link hierher
</a>

Hierbei wird das Attribut href des Links auf das Ergebis von here/absolute_url geändert. Das Attribut href wurde für dieses Element bereits definiert, d.h., wenn ein Design-Programm diese Seite öffnet, sieht es ein gültiges Element (auch, wenn der Link vielleicht so lange keinen Sinn macht, bis die Seite verarbeitet worden ist). Es folgen einige Beispielausgaben:

<a href="http://plone.org/Members/andy/book">Link hierher</a>

Da jedes Element mehrere Attribute haben kann, erlaubt tal:attributes die Änderung eines oder mehrerer Attribute gleichzeitig, indem mehrere Anweisungen verwendet werden. Um mehrere Attribute gleichzeitig zu ändern, trennen Sie die Anweisungen mit einem Semikolon (;). Falls das Attribut oder die Anweisung ein Semikolon enthält, können Sie dieses mit einem weiteren Semikolon direkt davor schützen (;;). Tun Sie Folgendes, um beispielsweise href und title im Element zu ändern:

<a href="#"
   tal:attributes="href context/absolute_url;
      title context/title_or_id">Link</a>

Die Ausgabe dieses Beispiels ist folgende:

<a href="http://plone.org/Members/andy/book" title="Plone Book">Link</a>

Die Tags tal:attributes und tal:replace schließen einander aus, weil replace das Element entfernt. Das Zope Page Templates-System stellt fest, wenn beide verwendet werden, gibt dann eine Warnung aus und ignoriert den tal:attributes-Teil. Falls der Ausdruck zu default ausgewertet wird, wird keine Änderung vorgenommen. Beispiel:

<a href="#"
    tal:attributes="href
        python:request.get('message', default)">
    Link</a>

In diesem Beispiel verwende ich die Funktion get auf dem Objekt request. Falls die eingehende Anfrage nach der Seite die Variable message enthält, wird der erste Wert verwendet, d.h. message. Wenn die Variable message nicht vorhanden ist, wird der zweite Wert, default, benutzt. Daher erfolgt allein durch die Übergabe des Parameters message eine Änderung.

tal:condition: Bedingungen auswerten

Mit der Anweisung tal:condition kann eine Bedingung getestet werden, bevor das Element dargestellt wird. Beispiel:

<p tal:condition="request/message">
    Es gibt eine Message
</p>
<p tal:condition="not: request/message">
    Keine Message
</p>

Hierbei wird der Absatz mit dem Text message nur dann dargestellt, wenn die Variable request ein Attribut hat und dieses zu True ausgewertet wird. Der Test einer Bedingung ist jedoch sinnlos, falls das Gegenteil der Bedingung nicht getestet werden kann. Dies leistet der negierte Ausdruck. Das Präfix not: invertiert die Anweisung, d.h., not: request/message wird dann zu True ausgewertet, falls die Anfragevariable message zu False ausgewertet wird.

In TAL wird Folgendes zu False ausgewertet:

  • Die Zahl Null
  • Alle Fließkomma- oder komplexen Zahlen, die als null ausgewertet werden (z.B. 0.0)
  • Strings der Länge null (z.B. "")
  • Eine leere Liste oder ein leeres Tupel
  • Ein leeres Dictionary
  • Der Wert None in Python
  • Der Wert nothing in TALES

Folgendes wird zu True ausgewertet:

  • Der Wert default
  • Alle Zahlen, die von null verschieden sind
  • Strings, die nicht leer sind
  • Strings, die nicht nur aus Leerzeichen bestehen (z.B. "   ")
  • Alles andere
tal:content: Text hinzufügen

Die Anweisung tal:content in einem Page Template ist die wahrscheinlich am häufigsten verwendete Anweisung. Sie ist auch eine der einfachsten, da sie den Inhalt eines Elements durch den angegebenen Wert ersetzt. Beispiel:

<i tal:content="context/title_or_id">Ein Titel</i>

Die Ausgabe des Beispiels lautet:

<i>Ein Titel</i>

Hierbei wird der Text Ein Titel durch den Wert des Ausdrucks context/title_or_id ersetzt. Falls der zu ersetzende Text HTML-Elemente enthält, werden diese geschützt. Der zu ersetzende Text wird standardmäßig HTML-geschützt. Das Präfix structure erlaubt, dass HTML eingegeben wird, ohne dass die Elemente geschützt werden. Beispiel:

<i tal:content="structure here/title_or_id">HTML nicht schützen</i>

Falls das Element mit den Attributen tal:content weitere Elemente enthält, werden auch diese Elemente alle ersetzt. Die Tags tal:content und tal:replace schließen sich gegenseitig aus und können nicht beide im gleichen Element vorkommen, ohne dass ein Fehler dabei auftritt. Falls der Wert default lautet, bleibt der Inhalt unverändert.

tal:define: Variablen definieren

Mit der Anweisung tal:define können im Template Variablen erzeugt und wiederverwendet werden. Beispiel:

<p tal:define="title here/title_or_id">
    ... <i tal:content="title">Ein Titel</i> ...
</p>

In diesem Beispiel wird die Variable title erzeugt, und es wird ihr das Ergebnis von here/title_or_id zugewiesen. Später wird die Variable in der Anweisung tal:content benutzt. Standardmäßig wird diese Variable nur im lokalen Geltungsbereich des aktuellen Elements erzeugt. Im vorigen Beispiel können daher nur Elemente im Absatz die Variable title benutzen. Sie können die Variable an einer beliebigen Stelle in der Anweisung neu definieren oder in anderen Elementen so oft wiederverwenden, wie Sie möchten.

Um eine global benutzbare Variable zu erstellen, verwenden Sie das Präfix global. Dadurch wird der Zugriff auf die Variable von überall im Template ermöglicht, nicht nur aus dem definierenden Element. Beispiel:

<p tal:define="global title string:Foo bar">
    ... <i tal:content="title">Ein Titel</i> ...
</p>
<i tal:content="title">Immer noch ein Titel</i>

Plone bietet eine große Anzahl solcher globaler Definitionen, damit die Benutzer diese in eigenen Scripts einfach verwenden können. Wie bei allen solchen Definitionen gilt, dass sie sich in Zukunft verändern können, d.h., Sie sollten sie mit Bedacht einsetzen. Diese define-Anweisungen bedeuten, dass eine große Menge an globalen Variablen verfügbar sind. Um beispielsweise an den Titel Ihrer Plone-Site zu gelangen, können Sie einfach Folgendes aufrufen:

<p tal:content="portal_title" />

Diese define-Anweisungen finden Sie im ZMI, wenn Sie erst auf portal_skins klicken, dann auf plone_templates und schließlich auf global_defines. Eine vollständige Liste aller Definitionen samt Erklärung finden Sie in Anhang A.

tal:omit-tag: Elemente entfernen

Die Anweisung tal:omit-tag ist etwas ungewöhnlich. Mit ihr kann ein Tag entfernt werden. Da das Zope Page Templates-System den Gebrauch von HTML-Tags vorschreibt, benötigen komplizierte Seiten oftmals eine Menge Elemente und können dazu führen, dass Extra-Tags hinzugefügt werden. Bei dieser Anweisung wird das Tag entfernt, so dass nur sein Inhalt stehen bleibt. Beispiel:

<p tal:omit-tag="">Irgendein Text</p>

Die Ausgabe lautet:

Irgendein Text

In diesem Beispiel wird der Text Irgendein Text ausgegeben, aber der Tag drumherum wird nicht dargestellt. Die Anweisung tal:omit-tag hat einen Ausdruck als optionales Argument. Wenn dieser zu False ausgewertet wird, findet die Auslassung nicht statt. Folgende Anweisung z.B. tut nichts:

<p tal:omit-tag="nothing">Irgendein Text</p>

Eine Alternative zum Einsatz von tal:omit-tag ist der eines tal-Namespace, wie im Abschnitt "Nützliche Hinweise" in Kapitel 6 beschrieben wird.

tal:on-error: Fehler behandeln

Die Anweisung tal:on-error bietet die Möglichkeit, Fehler zu behandeln. Sie verhält sich eher wie tal:content, weil sie bewirkt, dass der Inhalt des Tags ersetzt wird. Aber sie wird nur dann ausgeführt, wenn ein Fehler auftritt.

Hier ist ein Beispiel:

<p  tal:content="request/message"
    tal:on-error="string: Keine Message">Message</p>

Wenn es hier einen Fehler bei der Auswertung des Ausdrucks request/message gibt, dann wird das Attribut on-error aktiviert. Es bewirkt, dass der Inhalt des Tags durch den Text Keine Message ersetzt wird.

Leider ist die Anweisung on-error sehr beschränkt. Das Tag kann nicht zwischen verschiedenen Fehlern unterscheiden und erlaubt nur einen einzigen Ausdruck, der ausgewertet und benutzt werden kann. Diese Einschränkung ist gewollt, damit das Tag nicht übermäßig verwendet wird. Eine Fehlerbehandlung ist wirklich sehr viel besser in der Logik Ihrer Anwendung aufgehoben.

Zum Glück können Sie bei allen Ausdrücken Alternativen in der Anweisung angeben, falls der erste Anweisungsteil weder zu True noch zu False ausgewertet wird, d.h., wenn ein Fehler auftritt. Alle Alternativen werden durch einen senkrechten Strich (|) voneinander getrennt, und es können mehrere Alternativen in einer Anweisung vorkommen. Wenn Sie sich auf Variablen in eintreffenden Anfragen verlassen, sollten Sie am Ende immer |nothing hinzufügen, um sicherzugehen, dass kein Attributfehler auftritt.

Beispiel:

<p
  tal:content="request/message"
  tal:condition="request/message|nothing">
    Es gibt eine Message
</p>
<p tal:condition="not: request/message|nothing">
    Keine Message
</p>

Dieses zweite Beispiel ist etwas wortreicher, aber aus mehreren Gründen empfehlenswert:

  • Der Designer sieht die positive und die negative Bedingung.
  • Sie können eine kompliziertere Fehlerbedingung behandeln, anstatt nur einen String auszugeben.
tal:repeat: Schleifen ausführen

Die Anweisung tal:repeat erlaubt Schleifendurchgänge über Objekte und ist eine der komplizierteren Anweisungen. Eine Schleife enthält den Wert, der bei jeder Iteration über die Ergebnisse zugewiesen werden soll. Dieser Wert ist durch ein Leerzeichen von den Ergebnissen getrennt, über die iteriert wird.

Hier sehen Sie ein Beispiel für Schleifen:

<table>
  <tr tal:repeat="row context/portal_catalog">
    <td tal:content="row/Title">Title</td>
  </tr>
</table>

In diesem Beispiel gibt der Ausdruck here/portal_catalog eine Liste von Ergebnissen zurück. Da die Wiederholung beim row-Tag der Tabelle beginnt, wird für jede Zeile in der Ergebnisliste eine neue Zeile in der Tabelle erzeugt. Wie bei tal:define findet in jeder Iteration über die Ergebnisse eine Zuweisung an eine lokale Variable, in diesem Fall row, statt. Dieses Beispiel gibt für jeden Eintrag in der Ergebnisliste eine Zeile aus.

In der repeat-Anweisung können Sie auf einige nützliche Variablen wie die laufende Nummer der aktuellen Iteration zugreifen. Darauf können Sie über die Variable repeat zugreifen, die zum Namespace hinzugefügt wird. Um beispielsweise auf die laufende Nummer zuzugreifen, benutzen Sie Folgendes:

<table>
  <tr tal:repeat="row context/portal_catalog">
    <td tal:content="repeat/row/number">1</td>
    <td tal:content="row/Title">Title</td>
  </tr>
</table>

Die vollständige Liste aller in repeat verfügbaren Variablen lautet:

  • index: Dies ist die laufende Nummer, beginnend bei null.
  • number: Dies ist die laufende Nummer, beginnend bei eins.
  • even: Dies ist True bei geradem Iterationsindex (0, 2, 4, ...).
  • odd: Dies ist True bei ungeradem Iterationsindex (1, 3, 5, ...).
  • start: Dies ist True bei der ersten Iteration.
  • end: Dies ist True bei der letzten Iteration.
  • length: Dies ist die Gesamtzahl an Iterationen.
  • letter: Dies ist die Iterationszahl als Kleinbuchstabe (a-z, aa-az, ba-bz, ..., za-zz, aaa-aaz, usw.).
  • Letter: Dies ist eine Großbuchstabenversion von letter.
  • roman: Dies ist die Zahl mit römischen Ziffern in Kleinbuchstaben (i, ii, iii, iv, v, usw.), beginnend bei eins.

Im repeat-Namespace sind zwei weitere Werte verfügbar, die recht ungewöhnlich sind und selten verwendet werden, first und last. Mit diesen beiden Variablen können Sie Informationen über die Daten der Iteration speichern. Durch die Verwendung des Werts, den Sie in einem Ausdruck speichern möchten, wird ein boolescher Wert zurückgegeben. Bei der Variablen first gibt True an, dass dieser Wert zum ersten Mal in der Iteration aufgetreten ist. Entsprechend gilt bei der Variablen last, dass True anzeigt, dass der Wert zum letzten Mal in der Iteration aufgetreten ist.

Hier ist ein Beispiel dafür:

<ul>
  <li tal:repeat="val context/objectValues">
    First: <i tal:content="repeat/val/first/meta_type" />,
    Last: <i tal:content="repeat/val/last/meta_type" />:
    <b tal:content="val/meta_type" />,
    <b tal:content="val/title_or_id" />
  </li>
</ul>
tal:replace: Text hinzufügen

Die Anweisung tal:replace ähnelt tal:content, mit dem Unterschied, dass das gesamte Tag entfernt wird.

Beispiel:

<p tal:replace="context/title_or_id">Ein Titel</p>

Hiermit wird das Ergebnis des Ausdrucks context/title_or_id angezeigt, aber die Absatz-Tags werden aus dem Ergebnis entfernt. Das ist gleichbedeutend mit dem Folgenden:

<p
  tal:content="here/title_or_id"
  tal:omit-tag="">Ein Titel</p>

Falls das Element mit der Anweisung tal:replace weitere Elemente enthält, werden diese Elemente alle ersetzt. Die Anweisung tal:replace können Sie nicht zusammen mit tal:attributes oder tal:content verwenden, da sie sich gegenseitig ausschließen und ein Fehler auftritt, wenn Sie beide im gleichen Element benutzen.

Einführung in die Ausführungsreihenfolge

Die Reihenfolge, in der TAL-Attribute geschrieben werden, ist nicht die gleiche, in der sie ausgeführt werden, weil sie Teil von XML-Elementen sind (und XML kümmert sich nicht um die Reihenfolge von Attributen). Die Attribute werden in der folgenden Reihenfolge ausgeführt:

  1. define
  2. condition
  3. repeat
  4. content
  5. replace
  6. attributes
  7. omit-tag

Die Anweisungen content und replace können Sie nicht im gleichen Element verwenden, da sie sich gegenseitig ausschließen. Die Anweisung attributes zusammen mit replace oder omit-tag ist sinnlos in einem Element, weil die Attribute entfernt werden. Das on-error-Tag wird nicht erwähnt, weil es verwendet wird, wenn der erste Fehler in irgendeinem der vorigen Elemente auftritt.

Beispiel: Benutzerinformationen anzeigen

Damit Sie sich die bisher gelernten Punkte veranschaulichen können, werden Sie nun ein Page Template erstellen, das eine einfache Aufgabe hat: Informationen über einen Benutzer im System anzuzeigen.

In diesem Beispiel verwendet eine Firma Plone intern in einem Intranet. Jeder Angestellte ist in Plone registriert und kann sich anmelden. Es gibt jedoch keine einfache Seite, die alle Angestellten anzeigt oder darüber informiert, wie man sie kontaktieren kann. Sie werden eine einfache Informationsseite für die Benutzer erstellen, die für alle Benutzer deren E-Mail-Adresse, Homepage und Bild anzeigt und die angibt, wann sie sich das letzte Mal angemeldet haben.

Ein erster Prototyp dieser Seite ist mit TAL, TALES und ein wenig Grundlagenwissen über CMF-Werkzeuge (Content-Management-Framework) schnell erstellt. Weil die APIs (Application Programming Interfaces) zu diesen Werkzeugen aber leider sehr verworren sind, ist ein Teil dieses Codes länger, als er sein sollte. Seien Sie erst einmal unbesorgt wegen der API dieser Werkzeuge, sie werden in Kapitel 9 behandelt. Wenn Sie das API erst einmal als gegeben hinnehmen, können Sie sich auf TAL konzentrieren.

Zuerst müssen Sie ein Page Template erstellen. Klicken Sie also auf portal_skins, dann auf custom, und fügen Sie ein Page Template mit der ID user_info hinzu. Als Zweites werden Sie es wie folgt bearbeiten. Ein vollständiges Listing diese Page Templates finden Sie in Anhang A. Wenn Sie dieses Listing untersuchen, sehen Sie, dass es mit HTML- und body-Tags beginnt.

Aus Gründen der Bequemlichkeit setzen Sie die Hauptdefinitionen in ein div-Tag:

<div
  tal:omit-tag=""
  tal:define="
    userName request/userName|nothing;
    userObj python: here.portal_membership.getMemberById(userName);
    getPortrait nocall: here/portal_membership/getPersonalPortrait;
    getFolder nocall: here/portal_membership/getHomeFolder
    ">

In diesem div-Tag gibt es vier define-Anweisungen: eine, um an den Benutzernamen zu gelangen, der im request-Objekt übergeben wird, und eine weitere, um diesen Benutzernamen in ein Benutzerobjekt zu übersetzen. Die letzten beiden define-Anweisungen stellen sicher, dass Sie eine gültige Referenz auf die Methoden haben, mit denen Sie an die Bilder und Ordner der Benutzer gelangen. Auch diese sind bequem, weil sie den Code später vereinfachen. Ein solches div-Tag oder auch anderes Tag einzurichten, das eine Reihe von Definitionen enthält, ist ein übliches Vorgehen beim Zope Page Templates-System. Der Code wird dadurch einfach sauberer.

Als Nächstes erstellen Sie zwei einfache Bedingungen, um zu prüfen, ob Sie einen Benutzer haben:

<p tal:condition="not: userName">
    Keinen Benutzernamen gewählt.
</p>
<p tal:condition="not: userObj">
    Dieser Benutzername existiert nicht.
</p>

Wenn die Anfrage keinen Benutzernamen enthält, resultiert der Ausdruck request/username|nothing darin, dass userName gleich nothing ist, und der einfache Test schlägt fehl. Wenn der Benutzername ungültig ist, wird userObj zu None, und es werden Fehlermeldungen für diese beiden Bedingungen ausgegeben.

Nun sind Sie so weit, dass Sie den Benutzer bearbeiten können:

<table tal:condition="userObj">
  <tr>
    <td>
      <img src=""
      tal:replace="structure python: getPortrait(userName)" />
    </td>

Da Sie einen Benutzer nur dann anzeigen können, wenn Sie einen gefunden haben, werden Sie sicherstellen, dass es eine einfache Bedingung für diese Tabelle tal:condition="userObj" gibt. Um das Bild eines Benutzers anzuzeigen, verwenden Sie die zuvor definierte Methode getPortrait. Diese Funktion gibt das gesamte Tag zurück, d.h., das structure-Tag stellt sicher, dass das ganze Bild korrekt dargestellt wird. Als Nächstes möchten Sie einige Eigenschaften wie name und email anzeigen. Im Folgenden wird dies für eine dieser Optionen, den home-Ordner, gezeigt:

<li
    tal:define="home python: getFolder(userName)"
    tal:condition="home">
    <a href=""
        tal:attributes="href home/absolute_url"
        >Home-Ordner</a>
</li>

Zuerst verwenden Sie ein define, um an den Ordner zu gelangen, und weisen ihn der Variablen home zu. In einer Plone-Site ist das Erstellen eines home-Ordners für einen Benutzer optional, d.h., beim Verweis auf einen Ordner müssen Sie sicher sein, dass dieser auch existiert. Wegen der Ausführungsreihenfolge von TAL kommt die Definition vor der Bedingung. Danach zeigen Sie einen Link auf den Ordner mit Hilfe des Ordnerattributs absolute_url an.

Dieses Page Template enthält ein paar weitere Zeilen, um einige andere nützliche und aufregende Eigenschaften zu finden, die es dem Benutzer zeigen kann. Wie bei den meisten Dingen in Plone kommt es darauf an, die korrekten API-Aufrufe zu finden und die Ausgabe entsprechend weiterzuverarbeiten.

Die Seite endet schließlich mit dem Schließen aller relevanten Tags. Wenn alles gut geht, sollten Sie die Seite aufrufen können, indem Sie auf den URL http://ihresite/user_info?userName=[einbenutzer] zugreifen, wobei einbenutzer ein vorhandener Benutzername in Ihrer Plone-Site ist.

Momentan ist dieses Page Template ziemlich beschränkt. Nur ein Benutzer mit Managerrechten kann diese Seite sehen, sie kann nur jeweils ein Mitglied zu einem Zeitpunkt anzeigen, und die Information über diesen Benutzer ist recht mager. In Kapitel 6 werde ich zeigen, wie Sie dieses Beispiel ausbauen und einiges an Wiederverwendbarkeit von Komponenten hinzufügen - sowie die Möglichkeit, den Text in andere Sprachen zu übersetzen.


Andy McKay: Plone. Addison-Wesley 2005
Diese online Version wurde mit Hilfe des 'PloneBookDE' Produkts von docs.neuroinf.de/products erstellt.
Es wurde zuletzt von
loesch am 2006-01-11 13:38 aus der fallback Quelle aktualisiert.

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: