DTML
DTML ist Zopes Tag-basierte
serverbasierte Präsentations- und Scripting-Sprache (wie
z.B. SSI, PHP, PSP und JSP). DTML dient dem Anlegen modularer
und dynamischer Web-Schnittstellen, unterstützt die Wiederverwendung
von Inhalten und Layout, die Formatierung heterogener Daten
und die Trennung der Präsentation von Logik und Daten. Konkrete Anwendungsfälle
sind Aufrufe von Skripten, Suchanfragen oder Formularverarbeitung,
und es können neben HTML auch andere Text-Typen generiert
werden (z.B. eMail-Nachrichten). DTML ist für die Präsentation
von Objekten zuständig und wird von Web-Designern verwaltet,
während der Logikaspekt, z.B. komplexe
Algorithmen oder Stringverarbeitung mit Hilfe von Python und Perl
realisiert werden sollte.
Grundlegende DTML-Tags
DTML-Kommandos werden
als Tags geschrieben, die mit dtml- beginnen. Es gibt
singleton- und block-Tags (müssen geschlossen werden).
Das var-Tag: Das var-Tag setzt Variablen
in DTML-Skripte und -Dokumente ein, z.B. Strings. Das Verhalten des var-Tags
kann über Attribute beeinflusst werden, z.B. ein optionales Attribut
mit Standardwert, falls eine Variable nicht gefunden werden
kann: <dtml-var Spannweite missing="Spannweite unbekannt">.
Manche Attribute haben keine Werte, z.B. kann eine eingesetzte
Variable mit dem upper-Attribut in Großbuchstaben konvertiert
werden: <dtml-var exclamation upper>. Die wichtigsten Attribute sind
html_quote, missing und fmt (Diese Attribute, die Syntax von
var-Tag-Ausdrücken und der Umgang mit Python-Ausdrücken
werden im Anhang erläutert).
Die Suche
nach Variablen erfolgt zuerst im aktuellen Objekt, dann in seinen
Behältern (i.e.S. Ordner) und schließlich in der Web-Anfrage
(Formulare und Cookies). Misslingt die Suche, wird eine Ausnahme ausgegeben
und die DTML-Ausführung angehalten. Die Tag-Basierung von DTML
kommt darin zum Ausdruck, dass z.B. für mehrfach benutzbare
HTML-Fragment wie Header und Footer Tags definiert werden: Beispiel:
Es existiere ein Ordner "Futtertaschen" mit dem Titel "Alfreds
Lustige Futtertaschen" und ein DTML-Skript "Preisliste" folgenden
Inhalts:
=> Zope fügt
einen Header, Titel und Footer in die resultierende Web-Seite ein:
Zuerst wird der standard_html_header
und -footer erfolglos im aktuellen Objekt (DTML-Skript Preisliste)
und in dessen Behälter (Ordner Futtertaschen) gesucht.
Erst im Root-Ordner wird Zope fündig und fügt
die Ergebnisse der Skriptausführung ein. Die Variable title
wird im Ordner "Futtertaschen" gefunden und eingesetzt.
Das in-Tag: In den meisten Web-Anwendungen wird Iteration
angewandt. Das in-Tag von DTML iteriert über eine Folge von Objekten
und führt für jedes Objekt einen Prozess-Block aus. Die allgemeine
Syntax ist wie folgt:
<dtml-in expr="...">
Anweisungsblock
</dtml-in>
Die Arbeitsweise des
in-Tags und ein Beispiel finden sich im Anhang.
Das if-Tag:
Das if-Tag wertet eine Bedingung aus und führt aufgrund des
Ergebnisses verschiedene Aktionen aus, was die Anpassung von Web-Seiten
ermöglicht (Beispiels-Bedingung im Anhang). Der Block innerhalb des if-Tags
wird ausgeführt, wenn die Bedingung wahr ist. if-Tags sind
beliebig tief schachtelbar und arbeiten genauso wie if-Statements
in Python.
Else-
und Elif-Tags: Der if-Block kann auch ein else- oder elif-Singleton-Tag
enthalten. Hinter einem else-Tag steht eine Aktion, die bei einer unwahren
Bedingung aufgerufen wird. Mit Hilfe des elif-Tags können mehrere
Bedingungen in einem Block dargestellt werden können. Elif-Tags können Bedingungen sowohl
mit Namens- als auch mit Ausdrucks-Syntax prüfen.
Dynamisch erworbener Inhalt
Der Begriff des 'Erwerbens'
(acquisition) bezieht sich auf den dynamischen Gebrauch von
Inhalten und Verhaltensregeln aus übergeordneten Objekten.
Dieses Prinzip kann z.B. dazu genutzt werden, header für
verschiedene Bereiche einer Site einzurichten. Wird z.B. ein neuer
standard_html_header in einem Ordner angelegt, ersetzt dieser
den allgemeinen header für diesen Ordner und alle Unterordner:
Beispiel: Man lege im Ordner "Futtertaschen" einen Ordner mit
der id "Grün " und darin ein DTML-Dokument "standard_html_header"
an:
<html>
<head>
<style type="text/css">
body {color: #00FF00;}
p {font-family: sans-serif;}
</style>
</head>
<body>
Dieses HTML-Fragment kann nun als Header
benutzt werden. Es benutzt CSS (Cascading Style Sheets), um
das Aussehen und Verhalten der Web-Seite zu verändern:
Abb. 7: Dokument
mit eingerichtetem Header
Der Header wird nun von allen Web-Seiten
im Ordner Grün und seinen Unterordnern benutzt. Dieser
Prozess kann für Unterordner weitergeführt werden.
Mit diesem Muster kann das Aussehen und Verhalten (von Teilen)
einer Web-Site schnell geändert werden. Zope unterstützt
damit wesentliche objektorientierte Prinzipien:
call |
Aufruf von Methoden ohne Einfügen
Ihrer Rückgabewerte in die Ausgabe |
comment |
Zu Dokumentationszwecken. Der Comment-Block
wird aus der Ausgabe entfernt |
tree |
Erzeugung dynamischer Bäume in
HTML zur Darstellung hierarchischer Daten. Die Navigationsansicht
von Zope ist mit Hilfe des tree-Tags realisiert |
return |
Spezifikation eines Rückgabewertes |
sendmail |
Formatierung und Senden von Email-Nachrichten.
Kann benutzt werden, um eine Verbindung zu einem Mail Host herzustellen |
mime |
Formatierung von Daten mit MIME . Damit
können Emails mit Anhängen in Zope verschickt werden
|
unless |
Gegenstück zum if-tag, d.h. Ausführung eines Blockes, wenn
die Bedingung nicht wahr ist |
raise |
Manuelles Generieren einer Ausnahme,
z.B. um einen Fehler zu signalisieren |
try |
Ausnahmebehandlung |
DTML-Dokumente
speichern Dokument-ähnliche Inhalte, z.B. könnten
Kapitel eines Buchs in einem DTML-Dokument gespeichert werden.
Allgemein gilt: Ist der Inhalt hauptsächlich Dokument-orientiert
und soll er auf einer Site von anderen Objekten dargestellt werden,
dann sollte er in ein DTML-Dokument kommen (oder eine Datei, wenn kein DTML-Scripting benötigt wird).
DTML-Methoden sind dazu gedacht, andere
Objekte zu verändern und darzustellen. DTML-Methoden
speichern normalerweise nicht viel Inhalt, es sei denn, der
Inhalt soll sich ändern oder anderen Inhalt manipulieren. Also gilt: DTML-Methoden, wenn es
einfache Logik ist oder andere Objekte darzustellen sind.
Python- oder Perl-basiert Skripte: Ratsam für die Codierung
komplexen Verhaltens
Zope-Skript-Objekte enthalten Code, der in Python oder Perl geschrieben ist und werden zum Schreiben von Programm-Logik verwendet. Python und Perl sind sehr beliebte und leistungsfähige Open-Source Programmiersprachen mit den gemeinsamen Merkmalen: leistungsfähige, rasche Entwicklung, einfache Syntax, viele Add-On-Bibliotheken, starke Unterstützung durch Benutzergemeinde und ein reichhaltiges Angebot an kostenloser Online-Dokumentation.
Beispiel:
Verarbeitung von Formulareingaben
Ein einfaches Beispiel für die Verwendung von
Skripten ist ein Online-Webformular zur Berechnung des Zinseszinsbetrages
von Schulden. Es werden folgende Informationen benötigt: Der
aktuelle Saldo (oder Schulden) - "kapital", Jahreszinssatz
als Dezimalzahl (beispielsweise 0,095) - "zinssatz", Zahl der
Zeitpunkte in einem Jahr, zu denen verzinst wird (normalerweise monatlich)
- "perioden" und Anzahl an Jahren ab jetzt, die berechnet
werden soll - "jahre".
Die Berechnung schließt folgende Prozedur
ein: Division des "zinssatz" durch "perioden" (normalerweise 12)
- Ergebnis "i", Multiplikation von "perioden" mit "jahre" - Ergebnis
"n", Potenzierung von (1 + "i") mit dem Exponenten "n", Multiplikation
des Ergebnisses mit dem "kapital" => Dies ist der neue Saldo (oder
die neuen Schulden)
Es werden zwei DTML-Methoden zinsFormular und
zinsDarstellung benötigt, um die Informationen vom
Benutzer abzufragen bzw. sie darzustellen, außerdem ein Python-Skript
berechneZinseszins, das die tatsächliche Berechnung
durchführt. Hier ist eine beispielhafte Seitenvorlage
zinsFormular zur Abfrage von "kapital", "zinssatz", "perioden"
und "jahre":
<html>
<body>
<form
action="zinsDarstellung" method="POST">
<p>Bitte
geben Sie die folgende Informationen ein:</p>
Ihr aktueller
Saldo (oder Schulden): <input name="kapital:float"><br>
Ihr Jahreszinssatz:
<input name="zinssatz:float"><br>
Verzinsungsperioden
pro Jahr: <input name="perioden:int"><br>
Anzahl
der Jahre: <input name="jahre:int"><br>
<input
type="submit" value=" Berechnen "><br>
</form>
</body>
</html>
Dieses Formular ruft die zinsDarstellung auf.
Nun wird ein Python-Skript berechneZinseszins erstellt,
dass die Parameter "kapital", "zinssatz", "perioden" und "jahre"
aufnimmt:
## Script (Python) "berechneZinseszins"
## Parameter = kapital,
zinssatz, perioden, jahre
##
"""
Zinseszinsrechnung
"""
i = zinssatz / perioden
n = perioden * jahre
return ((1 + i) **
n) * kapital
Die Parameter werden in
das Feld Parameters List und der Code in das Haupttextfeld eingegeben. Die
Kommentare sind beim Bearbeiten über das Web nicht nötig, aber
hilfreich beim Bearbeiten von Skripten über FTP. Dies gibt
den Saldo oder die Schulden zurück, der über Zeitraum
"jahre" verzinst wurde. Eine Seitenvorlage namens zinsDarstellung
ruft berechneZinseszins auf und gibt das Ergebnis zurück:
<html>
<body>
<p>Ihr
Gesamtsaldo (oder Ihre Gesamtschulden) einschließlich Zinseszins
über
<span
tal:content="years">2</span> Jahre beträgt:</p>
<p><b><span
tal:content="python: here.berechneZinseszins(kapital,
zinssatz,
perioden,
jahre)" >1,00</span> €</b></p>
</body>
</html>
Nach Eingabe von Saldo oder Schulden in der Seitenvorlage
zinsFormular und Klick auf Berechnen schickt zinsFormular die
gesammelten Informationen an zinsDarstellung, das wiederum das
Python-Skript berechneZinseszins aufruft. Die Darstellungs-Methode
verwendet den vom Skript zurückgegebenen Wert bei der entstehenden
Darstellung.