Der lange Pfad zum eigenen Zopeserver
Diese Seite befasst soll einen Einstieg in Zope3 bieten. Ein
gutes Buch kann er vermutlich aber nicht ersetzen.
Achtung: Der Crashkurs ist noch nicht fertiggestellt.
Vorher durchlesen...
Zope3 kommt mit einer Unmenge an Begriffen daher, die unter
ZopeGlossary kanalisiert werden. Ausserdem existiert ein im Aufbau befindliches Kochbuch (
CookBook ), in dem man Probleme nachschlagen sollte, bevor man herrumfragt. Ich lese regelmäßig die Mailingliste und übernehme alle dort beantworteten Fragen ins Kochbuch - insofern ich die Lösung verstanden hab

. Wer noch nie objektorientiert programmiert hat, sollte vorher dringend
ZopeForOopNewbies durchlesen.
Eingabe, Verarbeitung, Ausgabe
Der Zopeserver ist abgesehen von seiner Datenbank zustandslos und arbeitet streng nach dem EVA-Prinzip:
- Eingabe: Ein ReQuest (z.B. eine HTTP-Anfrage eines Browsers) trifft ein.
- Verarbeitung: Eine VieW (mehr dazu weiter unten) verarbeitet den ReQuest - benutzt dabei üblicherweise nur Informationen aus ...
- dem ReQuest (z.B. Benutzernamen, Password, Sitzungsinformationen in Cookies, ...)
- der ZodB, der Datenbank hinter Zope (wird weiter unten beschrieben)
- Ausgabe: Die VieW liefert etwas - z.B. eine Webseite - an den Browser zurück.
Wenn man z.B. ein
ForMular abruft um beispielsweise einen Telefonbucheintrag auf dem Zope-Server zu verändern, merkt sich der Zopeserver das nicht (zumindest nicht zwangsläufig). Änderungen werden erst durchgeführt, wenn das
ForMular ausgefüllt beim Zopeserver eintrifft.
Installation
Unter
ZopeInstallation ist beschrieben, wie man einen Zope-Server aufsetzt. Nach der Installation haben wir eine
Zope-instanz vor uns - ein kleines Verzeichnis mit Konfigurationsfiles und der zur Instanz gehörenden Datenbank (
ZodB ). Der Zope-Server selbst besteht aus endlos vielen Python-Dateien (Endung
.py ) und liegt in einem anderen Verzeichnis, dass nicht beschreibbar sein muss. Auf diese Weise können mehrere
ZopeInstances auf einem Server laufen - auch wenn das wegen des hohen Speicherbedarfs nicht immer ratsam ist.
Beim Start arbeitet die
ZopeInstance eine Konfigurationsdatei
etc/zope.conf ab, in der das unscheinbare Statement
site-definition $INSTANCE/etc/site.zcml auf eine Datei verweist, die in einer Zope-eigenen
XmL-Sprache
ZCML geschrieben ist. Diese Datei bildet die Wurzel des
ZcmL-Baumes, der bei jedem Start (und nur beim Start!) abgearbeitet wird. Durch verschachtelte Include-Anweisungen wird dabei jedes gewünschte Python-Paket und dessen Unterpakete in Zope registriert und kann
Komponenten zur Verfügung stellen.
Die
ZopeInstance lä[t sich idealerweise komplett im Browser verwalten. Dafür ist eine Management-Oberfläche - das
ZmI zuständig. Diese Oberfläche ist jedoch nicht in Stein gemeisselt - man kann in dieser praktisch alles auf eigene Bedürfnisse anpassen. Alles, was man im
ZmI sieht, sind sog.
VieWs (Erklärung siehe weiter unten) und damit abhängig vom
ContentObject, das man gerade betrachtet. Für ein
ConTainer-Objekt kann das z.B. eine Ansicht der enthaltenen Unterobjekte mit einer Möglichkeit, diese Umzubenennen sein.
An Zope2-Umsteiger:
- Das ZmI ist nicht für TTW-Entwicklung gedacht. In Zope3 wird aussschliesslich im Filesystem entwickelt. Das ZmI ist nur für das Zusammensetzen entwickelter Komponenten und zum Konfigurieren gut.
Eine Objektorientierte Datenbank steht Zope zur Seite. In dieser ist eine hierarchische Struktur aus
Content-Objekten und anderen Dingen ablegt. Durch
TraVersing kann man auf Objekte in den Tiefen der Datenbank zugreifen.
TraVersing findet z.B. beim Auswerten einer an die
ZopeInstance übergebenen
UrL stat.
ContentObjects sind die eigentlichen Daten, die eine
ZopeInstance verwaltet. Man kann sie mit Objekten in Dateisystemen vergleichen - es gibt Verzeichnisse und Dateien, allerdings keine Links. Ein Unterschied ist jedoch, dass man bei Zope auch direkt in Verzeichnisobjekten Daten ablegen kann und nicht nur in Dateien.
ContentObjects in der
ZodB kann man als Instanzen von Content-Klassen betrachten.
Eigene
ContentObjects entwirft man, indem man...
- (je nach Anwendungsfall mindestens) ein SchemaInterFace des ContentObjects schreibt
- eine Klasse für das ContentObject implementiert, die im einfachsten Fall praktisch keinen selbstgeschriebenen Programmcode enthalten muss
- Die Klasse per ZcmL registriert.
ContentObjects enthalten Attribute, in denen der eigentliche
Content lagert, den später der Nutzer im Internet sieht. Diese Attribute können auch
Links (sog.
KeyReferences) zu anderen
ContentObjects enthalten und spannen so den Graph auf, der in der
ZodB alle
ContentObjects zu etwas sinnvollem (z.B. einem Baum) verbindet.
Mehrsprachiger Content
Man sich im klaren darüber sein, ob Daten in den Objekten mehrsprachig abgespeichert werden sollen und wie man das anstellen will. Im einfachsten Fall könnte man z.B. den Titel als zwei Attribute
title_de und
title_en speichern (Zweisprachigkeit).
MpgSite bietet eine Möglichkeit, mit wenig Aufwand Attribute von Objekten in beliebig vielen Sprachversionen zu speichern:
FbI18n.
Um die Verwaltung zu erleichtern, macht man unter Zope3 heftigen Gebrauch von
ConTainern?. Das sind Objekte, die das Interface
IContainer erfüllen und damit ein sog. Python-Mapping zur Verfügung stellen - eine Zuordnung
Objektname zu
Objektreferenz . Der Zugriff auf ein Unterobjekt erfolgt dann so:
mein_unterobjekt=container_objekt['unterobjektname']
Auf diese Weise entsteht ein Baum, den man sich relativ leicht vorstellen und den man mit dem
ZmI leicht verwalten kann.
VieWs - Ansichten und Funktionen von Objekten
ContentObjects selbst haben erst einmal keinerlei Erscheinungsbild - dargestellt werden immer nur sog.
VieWs.
VieWs kann man sich als Funktionen vorstellen, die
an den Objekten hängen und z.B. über den Browser aufgerufen werden können. Eine Funktion an einem Kalenderobjekt könnte z.B.
Wochenansicht sein - diese würde dann z.B. eine HTML-Seite mit einer Wochenansicht des Kalenders zurückliefern.
Was
VieWs von richtigen Funktionen unterscheidet, ist, dass sie in Wirklichkeit andere Objekte sind, die sich das anzuzeigende
ContentObject vornehmen und damit irgendetwas anstellen. Das Objekt selbst muss von der
VieW nichts wissen. Zugeordnet wird die
VieW (es handelt sich dabei um einen Objekt-auf-HTML-AdapTer) durch die
Komponenteninfrastruktur von Zope3 (mehr dazu weiter unten).
VieWs sind allerdings nicht auf das Zurückliefern von HTML beschränkt - man kann z.B. auch
VieWs schreiben, die z.B. in einem Verzeichnis-Objekt ein Unterobjekt entfernen und dann auf eine andere Seite (z.B. die
Verzeichnisansicht ) weiterleiten. Dabei wären die zurückgelieferten HTML-Daten uninteressant - nur die Funktionalität (Datei gelöscht) ist von Interesse.
VieWs an einem Objekt haben meist einprägsame Namen (die Namen sind frei wählbar) wie
edit.html (ein Edit-ForMular, mehr dazu weiter unten),
index.html /
view.html - die Standardansicht oder
printable.html (Unter
MpgSite die
Druckansicht) eines
ContentObjects.
Genauer: *
VieWs hängen nicht an Objekten, sondern werden an sog.
InterFaces festgemacht. Sobald ein Objekt das
InterFace einer
VieW erfüllt, ist diese für das Objekt verfügbar.
Beispiel: Das Objekt
/waldbewohner/Eiche erfüllt das
InterFace IBaum . Am
InterFace IBaum sind für alle HTTP-ReQuests die
VieWs giessen.html und
abholzen.html festgemacht. Deshalb führt der Pfad
/waldbewohner/Eiche/giessen.html zu einer existierenden
VieW .
Hinweise:
- In VieWs werden Daten für den aktuellen Benutzer/Betrachter aufbereiter. Um Daten zu Internationalisieren, muss man bestimmte Regeln einhalten: InterNationalisation.
- VieWs können selbst auch VieWs haben, was eine weitere Abstraktionsebene erzeugt.
- Um das bilden von VieWs aus UrLs kümmert sich der TraVersing-Prozess.
Formulare
VieWs können extrem komplex sein - z.B. generieren
Formulare eine HTML-Seite entsprechend der im entsprechenden
ContentObject abgespeicherten Daten. Der Benutzer kann das
ForMular bearbeiten und der Browser schickt es an die selbe
VieW zurück. Dabei müssen/dürfen/sollten die Daten des
ForMulars nicht bereits beim ersten zurückschicken abgespeichert werden. Das
ForMular entnimmt wahlweise die dem
ReQuest die vom Benutzer geändertem (und auch die nicht veränderten) Daten und schickt sie wieder an den Benutzer zurück - solange, bis der entsprechende Button zum abspeichern der
ForMular -Inhalte gedrückt wurde.
Hinweise:
- Zope3 kann ForMular -Daten auf die Einhaltung gewisser Regeln überprüfen ( siehe InterFace#ConStraints ) und Pro-Feld-Fehlermeldungen ausgeben.
Beispiel: Das Textfeld eMail darf keine Sonderzeichen enthalten.
- Zope3 kann ausserdem Zusammenhänge zwischen Feldern auf korrektheit überprüfen (sog. InVariants ).
Beispiel: Wenn die Has eMail -Checkbox angecheckt ist, darf das Textfeld eMail nicht leer sein.
- Zwei ZcmL
WidGets sind Objekte, die sich um die Darstellung und Verarbeitung von Daten für bestimmte
ReQuests kümmern.
Oftmals reicht zur Beschreibung folgende Aussage:
WidGet sind Objekte, die sich um die Darstellung von Feldern von
ContentObjects in HTML-
Formularen kümmern.
Oft hat man nur mit sogenannten
InputWidgets zu tun. Das sind
WidGet, die zum einen
ForMular -felder generieren und auf die vom Browser zurückgelieferten Daten wieder in ein
ContentObject speichern können. Anzeigen kann man Daten zwar über sog.
DisplayWidgets, jedoch wünscht man meist mehr Einfluss auf z.B. die Form der Einbettung von Daten in HTML-Daten.
PageTemplates sind HTML-Fragmente (es sind auch komplette HTML-Seiten denkbar, das ist aber nicht üblich). Solche Templates sind das Verbindungsstück zwischen Content und HTML-Seiten und werden intensiv in
VieWs genutzt.
PageTemplates werden am besten als wohlgeformtes
XmL geschrieben und lassen sich deshalb auch mit jedem
XmL-Editor bearbeiten. Ausnahmen wie z.B. beim
<br> -HTML-Tag sind machbar, aber sollten vermieden werden.
PageTemplates lassen sich leicht
Internationalisieren und auch
lokalisieren?.
In
PageTemplates kommen mehrere
XmL-Namensräume zum Einsatz, die für die Umwandlung des Templates in ein fertiges
XmL-Dokument entscheident sind - Informationen darüber gibt's unter
PageTemplates#NameSpaces .
LayeR sind Sammlungen von
VieWs, die
etwas gemeinsam haben . Üblicherweise realisiert ein
LayeR so etwas wie ein einheitliches Thema einer Webseite, das sich durch Umschalten auf einen anderen
LayeR. Dabei steht extreme Flexibilität zur Verfügung - man kann z.B. Benutzergruppenspezifisch die Oberfläche anpassen.
Hinter den Kullissen - Zope-Komponenten
Die Komponenteninfrastruktur
Zope3 verfügt über eine mächtige Komponenteninfrastruktur, die alles durchdringt. Das ermöglichte einfachen Austausch, Wiederverwendung und Erweiterung von Programmteilen.
Die Seite
ZopeComponents läßt sich darüber genauer aus.
Modularität durch Pakete
Zope3 besteht ausschliesslich aus simplen Python-Paketen - nicht aus speziellen Zope-Produkten wie das bei
Zope2 der Fall war. Um ein Paket für Zope3 zu erschliessen, muss es per
ZcmL konfiguriert werden - dafür liegt üblicherweise eine Datei
configure.zcml im Basisverzeichnis des Paketes und eine weitere
ZcmL -Datei, die nur eine Include-Anweisung enthält im
ZopeInstance-Verzeichnis
etc/package-includes/[Paketname]-configure.zcml . Pakete
includen dann wiederum ihre Unterpakete, wodurch ein weit-verzweigter
ZcmL-Baum bei jedem Start abgearbeitet wird.
Hinweis:
- Wo die per ZcmL eingebundenen Pakete liegen ist irrelevant - solange sie in einem Python zugänglichen Pfad liegen (dafür kann man im Zweifelsfall die Umgebungsvariable
PYTHONPATH bzw. das Zope-Startscript bin/runzope anpassen)
- Es ist noch etwas komplizierter - der ZcmL-Baum besteht eigentlich aus 3 Unterbäumen mit bestimmten Funktionen. Mehr dazu unter ZcmL#MultipleTrees .
Das Zope3-Sicherheitssystem
Zope3 macht den Zugriff auf praktisch alles davon abhängig, ob man jeweils die richtige
PerMission (Berechtigung) besitzt. Eine solche
PerMission ist erstmal nichts weiter, als ein String (z.B.
zope.ManageContent für die Berechtigung, ein Objekt zu bearbeiten). Jedem
ReQuest wird im Rahmen der Authentifikation (z.B. über das
PaU-UtilitY) ein
PrinCipal (Benutzerobjekt) zugeordnet. Eine
PerMission erhält man, indem im Laufe des
TraVersing-Prozesses auf
irgendeine Weise dem aktuellen
PrinCipal die entsprechende
PerMission zugeordnet wird.
Zope3 kennt sog.
SecurityPolicys - Objekte, die Möglichkeiten der Zuordnung
PrinCipal-zu-PerMission bereitstellen. Die Standard-SecurityPolicy kennt z.B. das Konzept der
Rollen (Warum das Rollen genannt wird, ist unklar - es handelt sich um Benutzergruppen), das eine zusätzliche Abstraktionsschicht zwischen
PerMissions und
PrinCipals aufbaut.
Die
SecurityPolicy ist austauschbar, jedoch sollten die meisten mir der Standard-Policy glücklich werden können.
Sicherheit entlang des Pfades
An jedem
ContentObject können Sicherheitsregeln (Zuordnungen zwischen
PerMissions,
Rollen und
PrinCipals) hängen. Diese Zuordnungen sind entweder positiv (gewähren Rechte oder Rollenmitgliedschaft) oder negativ (entfernen ein Recht oder eine Rollenmitgliedschaft wieder). Der Unix-Administrator im Author dieses Textes meint, man sollte nur positive Rechte benutzen.
Während die
VieW des aktuellen
ReQuests nun per
TraVersing aus der
UrL extrahiert wird, geht die
ZopeInstanz? durch den
ConTainer-Baum der
ZodB und hüllt die gefundenen Objekte jeweils mit
SecurityProxys ein, die anhand der
ZcmL-Konfiguration der jeweiligen Klasse entscheiden, ob man für genau dieses Objekt das Recht hat, auf bestimmte Attribute zuzugreifen oder nicht.
VieWs werden zusätzlich mit
PerMissions ausgestattet, um z.B. festzulegen, dass die
edit.html -VieW einer bestimmten Objektklasse nur von privilegierten
PrinCipals benutzt werden darf, die Standardansicht
index.html jedoch jeder sehen kann.
Ereignisse
Ereignisse werden benutzt, um bei bestimmten Anlässen Aktionen auszulösen. Ein Beispiel ist, dass Objekte beim Anlegen in den
Suchindex aufgenommen werden. Das könnte so laufen (in der Zope3-Wirklichkeit liegt noch eine Abstraktionsebene ( das
IntId -
UtilitY ) dazwischen).
Die Lektüre folgender Wiki-seite ist zu empfehlen:
EvenT.
Hinweis: In den
CataLog (die
Suchmaschine von Zope) werden Objekt eigentlich beim Hinzufügen in einen
ConTainer aufgenommen, nicht direkt beim Anlegen. Das ist oft deckungsgleich.
Metadaten
An praktisch alle
Persistenten Objekte kann man zusätzliche Informationen anhängen - sog.
MetaDaten, die in Zope3 per
AnnoTations realisiert sind. Dabei muss man praktisch nichts über die einzelnen Klassen dieser Objekte wissen - sie müssen lediglich ein bestimmtes
InterFace (
IAnnotatable ) implementieren.
Die Rauhe Wirklichkeit
In der Hoffnung, dass diese Seite das grundlegende Verständnis für Zope3 gebracht hat, wird hier auf zwei
Zope3-Bücher verwiesen. Diese führen durch die Programmierung jeweils einer umfangreichen Webanwendungen in die praktische Umsetzung von Zope3-Projekten ein. Diese Wiki steht helfend mit einem
Glossar und einem
Kochbuch zur Verfügung, wenn die Zope-Gurus, die die beiden Bücher schrieben mal wieder zuviel Wissen vorraussetzen

.
Viel Erfolg.
[Zurück zum Start]