Cheetah ist eine einfache, aber trotzdem mächtige Vorlagensprache für Python. Mit Cheetah kann man jede Art von Textdokumenten generieren. Der Haupt-Zweck ist natürlich das Generieren von HTML-Dokumenten.
Cheetah ist ein reines Python-Programm. Deshalb kann es normalerweise auf jedem Webserver ausgeführt werden der Python unterstützt. Selbst diese Seite, die du gerade liest, wurde mit Cheetah zusammengesetzt.
Ich zeige hier nur meine Versuche mit dem Apache-Webserver auf. Dieser unterstützt so genannte .htaccess-Dateien. Damit kann man die Einstellungen des Webservers für die eigene Website verändern. Unter Anderem kann man auch eine Handler-Datei für gewisse Dateitypen oder Dateien mit gewissen Endungen angeben.
Man kann den Apachen also so einstellen, dass immer dann wenn eine Cheetah-Vorlage mit der Endung .tmpl (=Cheetah-Vorlage) angefordert wird, ein Python-Programm aufgerufen wird. So ein Programm nennt man Handler.
Ich beschränke mich bei meinen Versuchen auf CGI (Common Gateway Interface). Wenn jemand einen einfachen Webspace gemietet hat, dann ist, wenn überhaupt, Python oft nur über das CGI verwendbar.
Zum Probieren verwende ich den Apachen, den ich mir irgendwann mal auf meinem Arbeitscomputer unter WindowsXP installiert habe. Und da auf meinem Computer sowiso auch Python installiert ist, kann der Apache automatisch auch Python-Programme als CGI-Programme verwenden. Da muss nichts zusätzlich installiert werden.
Noch einen Hinweis möchte ich los werden. CGI eignet sich hervorragend, wenn du nur etwas Kleines machen möchtest. Ein Formular ausfüllen lassen und dann per Email verschicken -- kein Problem. Den Benutzer in ein Formular etwas eingeben lassen und darauf reagieren -- kein Problem. Daten aus einer Datenbank auslesen und sogar Daten in eine Datenbank schreiben -- kein Problem.
Aber sobald du mehr machen möchtest und du dich nicht nur um ein paar dynamische Seiten kümmern musst, ist CGI einfach zu "low level" dafür. Du müsstest dich sogar um Sessiondaten selber kümmern. Chaching ist so gut wie nicht möglich. Jeder Aufruf einer Seite startet Python als eigenständigen Prozess neu. Das funktioniert bei bis zu (geschätzten) 20 Aufrufen die Minute sicher noch schnell genug. Aber wehe es werden mehr. -- Durch die vielen laufenden Python-Prozesse, durch den Speicherverbrauch der einzelnen Python-Prozesse und sogar durch das Starten der Python-Prozesse selbst, wird der Server stark ausgelastet. Da eine private Website selten so viele Zugriffe pro Minute haben dürfte, sollte das für Viele kein Problem darstellen. Wer mehr erwartet, sei auf den Erfahrungsbericht mit Cherrypy und Cheetah hingewiesen. Darin erkläre ich auch Cheetah etwas besser als hier.
Zum Glück braucht man keinen SSH-Zugang um Cheetah auf dem Webserver zu installieren. Es genügt, wenn man die TAR-Datei (Cheetah-2.0.tar.gz) lokal entpackt und dann einen der entpackten Ordner per FTP zum Webserver überträgt.
Cheetah-2.0
+---bin
+---src
+---Macros
+---Templates
+---Tests
+---Tools
¦ +---turbocheetah
¦ +---tests
+---Utils
+---optik
Für mich ist nur der Ordner src wichtig. Dieser muss nach Cheetah umbenannt werden.
Unterhalb des Cheetah-Ordners befinden sich Dateien und Ordner, die nicht unbedingt gebraucht werden. Diese kann man getrost löschen.
Das sind z.B. die Dateien und Ordner:
Übrig bleibt dieser Baum:
Cheetah
¦ CacheRegion.py
¦ CacheStore.py
¦ CheetahWrapper.py
¦ Compiler.py
¦ convertTmplPathToModuleName.py
¦ DummyTransaction.py
¦ ErrorCatchers.py
¦ FileUtils.py
¦ Filters.py
¦ ImportHooks.py
¦ ImportManager.py
¦ NameMapper.py
¦ Parser.py
¦ Servlet.py
¦ SettingsManager.py
¦ SourceReader.py
¦ Template.py
¦ TemplateCmdLineIface.py
¦ Unspecified.py
¦ Version.py
¦ __init__.py
¦
+---Macros
¦ I18n.py
¦ __init__.py
¦
+---Templates
¦ SkeletonPage.py
¦ SkeletonPage.tmpl
¦ _SkeletonPage.py
¦ __init__.py
¦
+---Tools
¦ ¦ CGITemplate.py
¦ ¦ MondoReport.py
¦ ¦ MondoReportDoc.txt
¦ ¦ RecursiveNull.py
¦ ¦ SiteHierarchy.py
¦ ¦ __init__.py
¦ ¦
¦ +---turbocheetah
¦ cheetahsupport.py
¦ __init__.py
¦
+---Utils
¦ htmlDecode.py
¦ htmlEncode.py
¦ Indenter.py
¦ memcache.py
¦ Misc.py
¦ VerifyType.py
¦ WebInputMixin.py
¦ __init__.py
¦
+---optik
errors.py
option.py
option_parser.py
__init__.py
Am Besten, man kopiert den Ordner Cheetah direkt in den Ordner in dem man die Web-Anwendung entwickeln möchte. Um den direkten Zugriff auf den Cheetah-Ordner zu verweigern, sollte man eine .htaccess-Datei mit diesem Inhalt in den Cheetah-Ordner legen.
.htaccess:
Order allow,deny
Deny from all
Infos über diese Apache-Anweisungen bekommt man hier:
Damit kann jetzt niemand mehr von außen auf diesen Ordner zugreifen. Man kann intern aber weiterhin damit arbeiten.
Ich habe mir das so vorgestellt:
print
, also per STDOUT, an den Apachen zurück gegeben.Da ich mit meinem lokal installierten Apachen (unter Windows XP) teste, arbeite ich direkt unterhalb des Ordners htdocs. Der htdocs-Ordner ist (in der Standardeinstellung des Apachen) der öffentliche Ordner, dessen Dateien auf Aufrage ausgeliefert werden (z.b. an einen Browser). In diesem htdocs-Ordner erstelle ich den Ordner cheetah_test. Und unterhalb dieses Ordners sollte auch der Cheetah-Ordner liegen.
Das sieht bei mir so aus:
J:\Apache\htdocs\
|
+---cheetah_test\
| |
| +---Cheetah\
| | |
| | + ...
| |
Der Ordner cheetah_test ist der Basisordner der neuen CGI-Anwendung und ist über die URL http://localhost/cheetah_test erreichbar.
Damit der Apache weiß, dass py-Dateien und tmpl-Dateien über CGI angesprochen werden sollen, muss man dies dem Apachen mitteilen. Dafür erstelle ich im Basisordner (cheetah_test) eine .htaccess-Datei.
.htaccess:
Options +ExecCGI
AddHandler cgi-script .py
AddHandler cheetah-template .tmpl
Action cheetah-template /cheetah_test/cheetah_handler.py
DirectoryIndex index.html index.htm index.tmpl
<FilesMatch "\.ini$">
Order allow,deny
Deny from all
</FilesMatch>
Die Einstellung Options +ExecCGI
gibt an, dass in diesem Ordner und in dessen Unterordner CGI erlaubt ist.
Die Einstellung AddHandler cgi-script .py
, weist Dateien mit der Dateiendung .py
als CGI-Programme aus.
Die Einstellung AddHandler cheetah-template .tmpl
, weist Dateien mit der Dateiendung .tmpl
als CGI-Programme aus.
Die Einstellung Action cheetah-template /cheetah_test/cheetah_handler.py
gibt an, dass immer dann wenn eine Datei vom Typ cheetah-template
, also eine Datei mit der Endung .tmpl
, angefordert wird, stattdessen das Programm /cheetah_test/cheetah_handler.py ausgeführt werden soll. Man achte auf den Slash (/) am Anfang des Pfades. Der Pfad beginnt für den Apachen, in meinem Fall, beim htdocs-Ordner.
Die Einstellung DirectoryIndex index.html index.htm default.htm index.tmpl
gibt an, dass immer dann, wenn kein Dateiname, sondern nur der Ordnername, übergeben wurde, im Ordner nach den Dateien index.html, index.htm, default.htm und index.tmpl gesucht werden soll. Die erste Datei die gefunden wird, wird statt dem Ordnerinhalt zurück gegeben. Damit kann man eine Standard-Datei für einen Ordner und dessen Unterordner festlegen.
Die Einstellungen in den FilesMatch-Tags geben an, dass von Außen niemand auf irgendwelche INI-Dateien zugreifen und diese auslesen kann. Das ist eine reine Sicherheitsvorkehrung die im Moment noch nicht wichtig ist.
Alles was ich dafür brauche, ist ein kleines Python-Programm, welches zuerst den CGI-Kopf (Header) erstellt und dann die übergebene Cheetah-Vorlage rendert und an STDOUT zurück gibt.
Nichts einfacher als das. :-)
cheetah_handler.py:
#!J:/Python25/python.exe
# -*- coding: iso-8859-1 -*-
import os
import sys
import cgi
import cgitb; cgitb.enable()
APPDIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, APPDIR)
from Cheetah.Template import Template
def main():
# Header
print "Content-Type: text/html;charset=iso-8859-1"
print
# Cheetah-Vorlage Rendern und zurück geben
tmpl_filename = os.environ.get("PATH_TRANSLATED", None)
assert tmpl_filename.endswith(".tmpl")
tmpl = Template(file = tmpl_filename)
print tmpl
if __name__ == "__main__":
main()
Im Kopf steht der genaue Pfad zu Python und das Encoding, in dem die Datei geschrieben wurde. iso-8859-1
ist unter Windows keine schlechte Wahl.
Nach dem Import der Python-Module füge ich den Anwendungspfad zum Pythonpfad hinzu. Damit haben die Cheetah-Vorlagen direkten Zugriff auf den Anwendungsordner -- egal in welchem Unterordner sich diese später befinden. Da ich den Anwendungsordner ganz an den Anfang des Pythonpfades setze, kann ich so auch sicher gehen, dass Cheetah von diesem Ordner importiert wird. Und sich nicht irgendein älteres, bereits installiertes Cheetah einschleicht.
Danach beginnt das Hauptprogramm. Zuerst wird der Header übermittelt -- ganz nach CGI-Vorgabe, mit einer Leerzeile vom Inhalt getrennt. Dann wird die Umgebungsvariable PATH_TRANSLATED
ausgelesen. In dieser befindet sich der Pfad zur aufgerufenen Cheetah-Vorlage. Man könnte die Prüfung, ob es sich auch wirklich um eine Datei mit der Endung .tmpl handelt, übergehen oder zumindest eine Korrekte Meldung an den Browser zurück geben. Aber mir genügt es im Moment, einfach nur ein assert
darauf los zu lassen.
Danach wird die Cheetah-Vorlage gerendert und mit print
an den Apachen zurück gegeben.
Jede Cheetah-Vorlage, die angefordert wird, wird also nicht direkt vom Apachen ausgeliefert. Es wird stattdessen dieses Programm aufgerufen, welches die angeforderte Cheetah-Vorlage rendert und das Ergebnis an den Apachen zum Ausliefern zurück gibt.
Jetzt fehlt uns nur noch eine Cheetah-Vorlage um die Anwendung zu testen.
hallo_welt.tmpl:
#attr $sentences = (
"Hier kommt der Wolf!",
"Wir sind gekommen um zu bleiben.",
"Das ist die perfekte Welle.",
"Aber jetzt geht's auf!",
)
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Ein geparstes Cheetah-Template</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<h1>Ich bin eine einfache Cheetah-Vorlage</h1>
<p><strong>Und hier - ein paar Sätze:</strong></p>
<ul>
#for $sentence in $sentences
<li>$sentence</li>
#end for
</ul>
</body>
</html>
Diese kann über die URL http://localhost/cheetah_test/hallo_welt.tmpl aufgerufen werden. Zum Demonstrieren von Cheetah habe ich eine kleine For-Schleife eingebaut. :-)
Dafür kann man in einer Cheetah-Vorlage direkt auf die CGI-Mechanismen zugreifen. Aber zuerst erstelle ich mir unterhalb des Ordners cheetah_test den neuen Ordner form_test.
J:\Apache\htdocs\
|
+---cheetah_test\
| |
| +---Cheetah\
| | |
| | + ...
| |
| +---form_test\
| | index.tmpl
| | datenempfang.tmpl
Ich arbeite im ersten Beispiel mit zwei Cheetah-Vorlagen. Eine Cheetah-Vorlage enthält das Formular. Die zweite Cheetah-Vorlage wird über den Action-Parameter des Formulars aufgerufen und zeigt die Formulardaten an.
index.tmpl:
#import cgi
#attr $form = cgi.FieldStorage()
#attr $title = "Formulartest - Startseite"
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>$title</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<h1>$title</h1>
## Fehlermeldung - BEGIN
## Wird nur angezeigt, wenn der Parameter *error* an diese Seite übergeben wurde
#if $form.has_key("error")
<div style="background-color: yellow; padding: 0.5em; margin: 1em;">
$form.getfirst("error")
</div>
#end if
## Fehlermeldung - END
## Eingabeformular - BEGIN
<form action="datenempfang.tmpl" method="GET">
<p>
Gib ein Wort ein und klicke danach auf die "Absenden"-Schaltfläche:
<input type="text" name="wort" value="$form.getfirst('wort', '')" />
<input type="submit" value="Absenden" />
</p>
</form>
## Eingabeformular - END
</body>
</html>
.
.
Leider konnte ich diese Seite nicht mehr fertig schreiben...
.
.
Ich programmiere Progressive Web Applications, Mobile Apps, Desktop-Programme und noch vieles mehr. Falls es dich interessiert, findest du mehr Informationen darüber auf meiner Business-Website.