Sonntag, 7. September 2008

entwickler.com Magazine Konferenzen Entwickler Akademie Entwickler-Forum Jobbörse Bücher
Software & Support Verlag




April 2006
aus Linux Enterprise Ausgabe: 12.2004
Tierisch gut
Das Cheetah Templating-System in der Praxis
von Markus Jais

Zwei der am meisten genutzten Technologien für die Entwicklung von dynamischen Websites sind heute Java Server Pages (JSP) und PHP. Aber auch Python hat in dieser Richtung einiges zu bieten wie z.B. die Python Server Pages oder das hier vorgestellte Cheetah-Templating-System. Diese Werkzeuge sind ähnlich mächtig wie PHP oder JSP und führen völlig zu unrecht noch ein Schattendasein in der Welt der Webentwicklung.


Was ist Cheetah?
Cheetah ist von einigen Python-Programmierern entwickelt worden, die teilweise auch schon an dem Webware-Framework [1] mitgearbeitet haben. Webware ist ein einfaches, aber leistungsfähiges Framework für die Webprogrammierung in Python. Wer mit Python Webanwendungen schreibt, sollte sich Webware unbedingt einmal näher anschauen. Die Entwickler von Cheetah waren mit den Python Server Pages von Webware nicht zufrieden und suchten nach einer besseren Lösung. Und so war Cheetah geboren. Es flossen Ideen von vielen anderen ähnlichen Lösungen ein wie z.B. dem Template Toolkit von Perl [2] oder Velocity [3] für Java. Das Ergebnis ist ein einfach zu benutzendes, aber trotzdem leistungsfähiges Templating-System, das zudem noch eine relativ umfangreiche Dokumentation besitzt, was bei vielen Open-Source-Projekten leider oft der Schwachpunkt ist. Nur ein paar mehr Beispiele wünscht man sich manchmal.

Installation
Die aktuelle Version von Cheetah bekommen Sie von dessen offizieller Homepage [4]. Oder sie können sich auch den aktuellen Sourcecode aus dem CVS holen. Wie das geht, ist auf der Cheetah-Homepage beschrieben. Die Installation ist denkbar einfach. Nachdem Sie Cheetah runtergeladen haben, rufen Sie einfach folgenden Befehl auf: $ python./setup.py install

Neben dem eigentlichen Cheetah-Sourcecode, der dort installiert wird, wo auch andere Python-Module liegen, werden zusätzlich noch die Programme cheetah und cheetah-compile, welche für die Arbeit mit Cheetah nützlich sind, aufgespielt.

Ein erstes Beispiel
Zum Einsteig schauen wir uns erst mal ein ganz triviales Beispiel an, damit Sie eine Vorstellung davon haben, worum es hier geht (vergl. Listing 1).

Listing 1

#!/usr/bin/env python

import Cheetah.Template
import time

spanish_numbers = ("uno", "dos", "tres")
current_time = time.localtime()

myTemplateDefinition = '''
<html><head><title>My first Tempatel</title>
<body>
<h2>date today: $day.$month.$year </h2><br>
<ul>
#for $number in $numbers
<li>$number</li>
#end for
</ul>
</body></html>'''

name_space = {'numbers' : spanish_numbers, 'year' : current_time[0], 'month' : current_time[1], 'day' : current_time[2]}

searchList = [name_space]

myTemplate = Cheetah.Template.Template(myTemplateDefinition, searchList)

print myTemplate


Dieses kleine Cheetah-Beispiel erzeugt eine einfache HTML-Seite mit dem aktuellen Datum als Überschrift und einer Liste mit den Zahlen von eins bis drei auf Spanisch. Dazu importieren wir Cheetah.Template und das time-Modul, welches wir für die Ermittlung der aktuellen Zeit benötigen. Das Gerüst für das zu erzeugende HTML speichern wir in der Variable mytemplateDefinition. Das Interessante daran sind jetzt zum einen in der Überschrift die Platzhalter $day, $mothy und $year. Und zusätzlich die #for-Schleife. Das gehört alles zur Syntax von Cheetah. Diese so genannte Template-Definition übergeben wir am Ende des Beispiels der Klasse Template aus Cheetah.Template. Zusätzlich müssen wir eine so genannte Search List übergeben, welche ein Dictionary (Hash) enthält. Jedes Element innerhalb der Search List definiert einen so genannten Namensraum (Namespace). Das Dictionary in unserem Beispiel hat als Key einen String, der später mit einem $-Zeichen davor in der Template-Definition verwendet werden kann, wie hier z.B. an dem Key year zu sehen ist. Auch die Liste mit den spanischen Zahlen kann einem Key in dem Dictionary zugewiesen werden. Mit Hilfe der #for-Anweisung kann dann wie in Python auch über dieses Liste iteriert werden. Am Schluss geben wir das ganze nur noch aus. Die Syntax von Cheetah ist der von Python sehr ähnlich, aber auch ohne vorherige Programmierkenntnisse ist das ganze leicht zu verstehen. Wenn Sie den Code in einem Python-Skript speichern und dieses ausführen, erhalten Sie folgende Ausgabe:

<html><head><title>My first Tempatel</title>
<body>
<h2>date today: 11.2.2004 </h2><br>
<ul>
<li>uno</li>
<li>dos</li>
<li>tres</li>
</ul>
</body></html>


Sie sehen, dass sowohl das aktuelle Datum als auch die spanischen Zahlen eingefügt wurden. Cheetah wird hauptsächlich im Bereich Webanwendungen eingesetzt. Es ist aber als Template-System natürlich nicht auf HTML beschränkt. Dies soll ein zweites Beispiel demonstrieren. Wir lesen aus einer CSV-Datei Informationen wie Namen und Geschlecht von verschieden Personen ein und erzeugen daraus SQL-Code, mit welchem eine Tabelle in einem SQL-Datenbank-System wie z.B. MySQL gefüllt werden kann. Das ganze ist keine besonders sinnvolle Anwendungen, demonstriert aber, dass man Cheetah auch für andere Sachen als Webanwendungen verwenden kann und zeigt zudem noch ein paar weitere interessante Sachen wie z.B. die Auslagerung der Template-Definition in eine eigene Datei. Hier die CSV-Datei:

Hans,Meier,m
Claudia,Huber,w
Peter,Haas,m


Wir wollen daraus SQL INSERT-Statements generieren, um diese Daten in eine Datenbank einzufügen. Je nach Geschlecht speichern wir die Anrede Herr oder Frau. Im Gegensatz zum ersten Beispiel speichern wir nun die Template-Definition in einer eigenen Datei, welche wir peopleTmpl.tmpl nennen (die Endung tmpl wird normalerweise für Template-Definitionen verwendet). Den Inhalt sehen Sie in Listig 2.

Listing 2

#for $person in $people
#if $person["sex"] == "m"
INSERT INTO people (vorname, nachname, anrede) values('$person["firstname"]', '$person["lastname"]', 'Sehr geehrter Herr');
#else if $person["sex"] == "w"
INSERT INTO people (vorname, nachname, anrede) values('$person["firstname"]', '$person["lastname"]', 'Sehr geehrte Frau');
#end if
#end for

Das ganze ist sehr ähnlich der Template-Definition aus dem ersten Beispiel, nur dass hier noch eine if-Abfrage hinzukommt. Mit Hilfe des folgenden Befehls $ cheetah-compile peopleTmpl.tmpl erzeugen wir die Datei peopleTmpl.py. Es lohnt sich, in diese generierte Python-Datei mal einen Blick zu werfen. Wer mehr darüber erfahren möchte, wie das ganze im Detail funktioniert, dem sei die Lektüre des Cheetah Developers Guide empfohlen, welchen man auch auf der Cheetah-Website findet. Um mit dem Ganzen jetzt unser SQL-Skript erzeugen zu können, benötigen wir noch ein kleines Python-Programm welches Sie in Listing 3 sehen.

Listing 3

#!/usr/bin/env python

import Cheetah.Template
import copy
from peopleTmpl import peopleTmpl

people_list = []
people_dict = {}
for line in file("people.csv"):
tmp_list = line.strip().split(",")
people_dict["firstname"] = tmp_list[0].strip()
people_dict["lastname"] = tmp_list[1].strip()
people_dict["sex"] = tmp_list[2].strip()
tmp_dict = copy.deepcopy(people_dict)
people_list.append(tmp_dict)
people_dict.clear()


name_space = {'people' : people_list}
searchList = [name_space]
myTemplate = peopleTmpl(None, searchList)

print myTemplate


Wie im ersten Beispiel importieren wir jetzt auch wieder Cheetah.Template. Das Modul copy hat nichts mit Cheetah zu tun, das brauchen wir nur, um den Namespace und die Search List zu erzeugen. Ohne die Verwendung von deepcopy würden wir nämlich mit clear den Inhalt des Dictionaries löschen, das wir vorher in die Liste eingefügt haben, da Python ja nur mir Referenzen arbeitet. Mit einer tiefen Kopie in eine temporäre Variable lässt sich das vermeiden. Das eigentlich interessante an diesem Beispiel ist der Import der Klasse peopleTmpl aus dem gleichnamigen, gerade erzeugten Modul. Diese autogenerierte Klasse erbt von Cheetah.Template, sodass wir die Search List direkt dem Konstrukter der Klasse peopleTmpl übergeben können. Der erste Paramter ist hier None, da wir ja keine Template-Definition mehr übergeben müssen.

Es gibt verschiedene Möglichkeiten, die hier gezeigten Beispiele mit Cheetah umzusetzen. Mehr dazu finden Sie in der sehr ausführlichen Dokumentation zu Cheetah.

Cheetah-Systax
Cheetah bietet eine sehr umfangreiche und leistungsfähige Syntax. Trotzdem bleibt das ganze übersichtlich und ist schnell zu erlernen. Das liegt vor allem auch daran, dass es fast identisch ist mit Pythons eigener Syntax. Man unterscheidet zwischen Platzhaltern mit einen $-Zeichen am Anfang (siehe Beispiele) und Anweisungen (Direktiven) wie z.B. #for- und #while-Schleife oder #if-Anweisungen.

Es gibt noch viel mehr Anweisungen als in den Beispielen zu sehen war, z.B. zum Importieren von Modulen, zum Erben von anderen Templates oder Python-Klassen und vieles mehr. Alle Möglichkeiten aufzuführen, würde den Umfang dieses Artikels bei weitem sprengen. Darum möchte ich hier auf die Cheetah-Dokumentation verweisen.

Weitere Eigenschaften
Cheetah ist natürlich noch viel mächtiger als ich bisher zeigen konnte. So besitzt es zum Beispiel einen Caching-Mechanismus, um die Performance noch zu optimieren, leistungsfähige Ausgabe-Filter, um die Ausgabe der Templates noch flexibler zu gestalten, und ein Framework zur Fehlerbehandlung. Zusätzlich beinhaltet Cheetah noch weitere nützlich Module und Templates die einem das Leben erleichtern.

Cheetah und Webware
Der ein oder andere Python-Entwickler kennt bestimmt das schon erwähnte Webware-Framework [1]. Es bietet eine Vielzahl von nützlichen Tools für die Entwicklung von Webanwendungen mit Python. Kernstück ist WebKit, welches Servlets ähnlich den Java Servlets für Python zur Verfügung stellt. Es gibt auch Python Server Pages (ähnlich den Java Server Pages) und noch vieles mehr. Wer Webanwendungen mit Python schreiben möchte, der sollte sich das unbedingt mal näher anschauen. Mit Webware ist Python eine hervorragende Alternative zu Java Servlets. Cheetah wurde teilweise von Webware-Entwicklern entwickelt (u.a. als Alternative zu den Python Server Pages) und arbeitet daher hervorragend mit Webware zusammen. Die von dem Befehl $cheetah-compile Templatedefinition generierte Python-Klasse ist auch ein gültiges Webware Servlet. Weitere Informationen zur Installation von Webware findet man auf dessen Website. Die Cheetah-Dokumentation enthält alles notwendige, um die generierten Servlets mit Webware zu verwenden. Das ganze lohnt sich auf jeden Fall auszuprobieren, da man damit eine sehr leistungsfähige, aber trotzdem einfach zu nutzende Software erhält, um auch komplexe Webanwendungen damit zu erstellen.

Alternativen
Jeder Software-Entwickler hat andere persönlichen Präferenzen und nicht jedem wird Cheetah gefallen. Eine mögliche Alternative sind die schon kurz erwähnten Python Server Pages (PSP) des Webware Projektes. PSPs haben eine andere Syntax, die den Java Server Pages sehr ähnlich ist. Auch für modpython [5] gibt es mittlerweile eine PSP-Implementierung. Einen sehr ähnlichen Ansatz verfolgt auch Spyce [6], welches u.a. auch die Möglichkeit bietet, eigene Tag-Bibliotheken zu schreiben. Auch Zope [7] bietet mit den Zope Page Templates (ZPT) einen interessanten Template-Mechanismus. Weitere Alternativen sind auch noch Quixote [8] und Woven Web Templating des Twisted-Frameworks [9]. Interessant dürfte auch noch coil [10] sein, ein MVC (Model View Controller)-Framework für Python, welches dem Java-Framework Struts nachempfunden ist. Es unterstützt u.a. auch Cheetah.

Ob Sie jetzt Cheetah verwenden oder eine der genannten Alternativen, hängt von Ihrem Anwendungszweck und Ihren Vorlieben ab. Alle Lösungen haben Vor- und Nachteile und wenn man genügend Zeit hat, sollte man sich alle mal ein wenig anschauen. Wenn Sie nicht über zu viel Zeit verfügen (und welcher Software-Entwickler hat schon zu viel Zeit?), dann dürfte Cheetah sicher eine gute Wahl sein.

Schlusswort
Die Trennung von Layout und Logik bleibt eine der wichtigsten Anforderungen an Webanwendungen. Cheetah ist nicht das perfekte Allheilmittel, aber so etwas gibt es auch nicht. Ich hoffe, ich konnte ein wenig das Interesse an Cheetah wecken und Ihnen die Philosophie dahinter ein wenig näher bringen. Falls Sie Cheetah jetzt interessant finden, würde ich Ihnen raten, sich die offizielle Dokumentation durchzulesen und sich noch ein wenig mehr damit zu beschäftigen. Dann können Sie selbst entscheiden, ob Cheetah für Ihre Anforderungen geeignet ist. Cheetah heißt auf deutsch übrigens Gepard. Diese faszinierenden Katzen sind leider sehr selten geworden. Wer sich näher für diese Tiere und deren Schutz interessiert, findet unter [11] weitere Informationen. Ich wünsche Ihnen viel Spaß mit Python und Cheetah.
Markus Jais ist Software-Entwickler. In seiner Freizeit trifft er sich mit Freunden, geht Wandern und beschäftigt sich mit Ruby, Perl, Python, Java, PHP, XML, MySQL, PostgreSQL und lernt Spanisch und Französisch. Im Internet ist er unter www.mjais.de/ zu finden.

Links

[1] webware.sourceforge.net/
[2] www.template-toolkit.org/
[3] jakarta.apache.org/velocity
[4] www.cheetahtemplate.org/
[5] www.modpython.org/
[6] spyce.sourceforge.net/
[7] www.zope.org/
[8] www.mems-exchange.org/software/quixote
[9] www.twistedmatrix.com/
[10] sourceforge.net/projects/coil/
[11] www.cheetah.org


    Hat Ihnen dieser Artikel gefallen? Dann abonnieren Sie das Entwickler Magazin direkt über unser Online-Formular.

zur vorherigen Seite
zurück
an den Anfang der Seite
nach oben
Diesen Artikel drucken
drucken
Diesen Artikel weiterempfehlen
empfehlen

Software & Support Verlag GmbH