Einstieg in die Zope- CMF- Plone-Welt

  • Send this page to somebody
  • Print this page
Einfach eine Sammlung von Links und Erkenntnissen, die mir hilfreich erscheinen, um den Einstieg in Python, Zope, CMF und Plone zu erleichtern. (Raphael Ritz, März 2003; übersetzt und aktualisiert, Juli 2003, September 2003)

Hauptanlaufpunkte im Web

Python: http://www.python.org

Zope: http://www.zope.org (die Zope-Community) und http://www.zope.com (die Firma Zope Corporation)

Zopes Content Management Framework (CMF) http://cmf.zope.org

Plone, ein sehr weit entwickeltes und ansprechendes Front-End zum CMF http://plone.org

Dokumentation

Python:

Zope:

CMF

Leider gibt es (noch?) keine umfassende Dokumentation des CMF, aber hier und da finden sich Ausführungen zu verschiedenen Aspekten (google is your friend). Die CMF-Distribution kommt selbst mit etwas Dokumentation, die über den 'Help'-Link des ZMI (Zope Management Interface) erreicht werden kann.

Plone

Sonstiges

Spezielle Werkzeuge zum Auffinden bzw. Generieren von Dokumentation

oder wie suche ich effektiv nach etwas zu meinem Problem:

  • Volltext durchsuchbare Mailing List Archive:
  • Werkzeuge, die Dokumentation erzeugen:
    • DocFinder (http://www.handshake.de/~dieter/pyprojects/zope/DocFinder.html) zusammen mit DocFinderEverywhere: http://www.zope.org/Members/shh/DocFinderEverywhere

      DocFinder unterstützt die Ermittlung der API (Application Programmer Interface) von individuellen Objekten (oder: "was kann ich denn hiermit wie machen") sowie das debugen von Sicherheitsproblemen. Es interpretiert Docstrings als Structured Text, was die Einbettung formatierter Dokumentation in den Source-Code ermöglicht, die dann sofort auch übers Web zugänglich ist.

    • HappyDoc: http://happydoc.sourceforge.net/

      HappyDoc extrahiert Dokumenation aus dem Python Quelltext kontextsensitiv. (Aus der Produktbeschreibung: HappyDoc is a tool for extracting documentation from Python source code. It differs from other such applications by the fact that it uses the parse tree for a module to derive the information used in its output, rather that importing the module directly. This allows the user to generate documentation for modules which need special context to be imported.)

    • Zpydoc: http://www.last-bastion.net/Zpydoc

      Zpydoc macht Pythons standard Dokumentationsformalismus innerhalb von Zope verfügbar. Im wesentlichen wraped es pydoc (und setzt noch etwas drauf).

Tipps und Tricks

(wie sie mir gerade einfallen) Eine ungeordnete Sammlung von Einsichten, die helfen sollen, einige der etwas trickreicheren Dinge in Zope zu verstehen.

  • Zopes Datenbank (die ZODB) und alternative Speichermechanismen

    Zope bringt seinen eigenen transaktionsbasierten, hierarchischen Objektspeicher mit, die ZODB (Zope's Object DataBase) http://www.zope.org//Members/runyaga/ZopeFAQs/WhatWhyHowZODB Auf der Festplatte liegt diese Datenbank in Form eines einzigen (womöglich sehr großen) Files in Pythons pickel Format.

    Dies wird als file system storage bezeichnet. Der Filename ist Data.fs und das File liegt in Zopes var Verzeichnis. Mit DBTab (http://hathaway.freezope.org/Software/DBTab ab Zope 2.7 standardmäßig dabei) kann man die Datenbank auch auf mehrere Files verteilen. Alternativen sind weiterhin directory storage http://dirstorage.sourceforge.net/index.html oder APE (adaptable persistence) http://hathaway.freezope.org/Software/APE. Darüber hinaus kann Zope mit jedem (vernünftigen) relationalen Datenbanksystem verknüpft werden.

  • Objekt/Attribut/Methoden-Ermittlung oder wie Zope sucht

    Dies ist offensichtlich eines der für Anfänger verwirrendsten Themen, da hier mehrere fortgeschrittenen Softwaretechniken zum Einsatz kommen.

    1. Mehrfachvererbung

    Da Zope in Python implementiert ist, sind Zope-Objekte Instanzen von Python-Klassen. Python unterstützt Mehrfachvererbung und Zope macht davon regen Gebrauch. Das heißt, wenn man eine Klasse wie in class myclass(baseclass1,baseclass2, ...) definiert, kann man von so vielen Klassen ableiten, wie man möchte. Diese Klassen können selbst wieder von beliebig vielen anderen Klassen abgeleitet sein, und so weiter. Daher ist es oft nicht einfach, herauszufinden, welche Methoden einer gegebenen Klasse zur Verfügung stehen, denn dazu muss man alle Basisklassen (und wiederum deren Basisklassen) inspizieren. Das genau macht der oben erwähnte DocFinder für einen, so dass man sich im ZMI direkt alle Basisklassen eines Objektes inklusive ihrer Methoden und Attribute anschauen kann. Zu beachten ist noch, dass die Reihenfolge, in der man die Basisklassen spezifiziert, bedeutsam ist, denn Python sucht von links nach rechts. Im Falle eines Konflikts (zwei oder mehr Basisklassen definieren dieselbe Methode auf womöglich unterschiedliche Art und Weise) wird einfach die zuerst gefundene genommen.

    Beispiel: Sagen wir mal, Sie möchten ihren eigenen behälterartigen Inhaltstypen (folderish content type) für das CMF definieren. Dazu leiten Sie von PortalContent und PortalFolder ab. Abhängig davon, ob Sie nun class myFolderishType(PortalContent,PortalFolder) oder class myFolderishType(PortalFolder,PortalContent) verwenden, werden Sie unterschiedliches Verhalten Ihres neuen Typen erhalten. Beispielsweise überschreibt PortalFolder die für die Anmeldung beim portal_catalog zuständigen Methoden indexObject() und reindexObject() mit pass (sprich: nichts tun). Daher wird im ersten Fall der neue Typ vom Katalog erfasst werde, im zweiten Fall jedoch nicht.

    1. Akquistion

    In der ZODB können Objekte nur in einem sogenannten Kontainer abgelegt werde, der sich selbst wiederum auch in einem Kontainer befinden muss, und so weiter (einzige Ausnahme: das Wurzelobjekt root). Dadurch wird eine hierarchische Struktur unter den Objekten definiert. Es ist diese Struktur, die sich das Konzept der Akquisition zunutze macht. Wenn eine Methode auf ein Objekt angewandt werden soll, über die das Objekt selbst jedoch nicht verfügt (weder selbst, noch auf dem Vererbungswege), setzt Zope die Suche nach der Methode im Kontainer des Objekts fort, und wenn sie dort nicht gefunden wird, in dessen Kontainer, usw. Die richtige Anwendung dieses Konzepts kann einem viel Arbeit ersparen, setzt aber etwas Nachdenken über eine geeignete Struktur voraus, d.h. es kommt eben darauf an, wo in der Objekthierarchie man was ablegt. Diese gerade beschriebene Art der Akquisition heisst genauer acquisition by containment, um sie von folgendem abzusetzen:

    Um das ganze etwas verwirrender zu machen, gibt es noch die Akquisition im Kontext (acquisition by context). Wenn man eine Methode auf ein Objekt anwenden möchte, so kann man dies tun, indem man den Pfad zum Objekt angibt und daran die Methode anhängt, wie in /topfolder/somefolderA/subfolder/object/mymethod (beachten Sie das URL-Format; Sie können das tatsächlich einfach mit Ihrem Browser so aufrufen). Angenommen, weder das Objekt noch einer seiner Kontainer verfügen nun über die gewünschte Methode, aber es gebe einen weiteren Kontainer somefolderB in topfolder neben somefolderA, der mymethod enthält. Wenn man nun den Pfad in obigem Aufruf erweitert zu /topfolder/somefolderB/somefolderA/subfolder/object/mymethod, dann wird die Methode gefunden. Man sagt nun, durch die Erweiterung des Pfades habe man den Kontext, in dem die Methode aufgerufen und damit gesucht wird, verändert, daher der Name.

    1. Skinning (soll/kann man das Übersetzen?)

    Skinning bezeichnet ein weiteres Konzept zur Erweiterung des Suchraumes für Methoden und Attribute, den das CMF mitbringt (und über den auch Zope 3 verfügen wird). Ich stelle mir das wie mehrere Suchpfade (wie bei einem Betriebssystem) nebeneinander vor, von denen ich einen aussuchen kann. Angenommen man hat mehrere Ordner f1, f2, ..., fn mit verschiedenen Versionen derselben Methoden (wobei allerdings nicht jeder Ordner jeweils alle Methoden beinhalten muss). Ein Skin wird nun wie folgt definiert: für Skin A suche zuerst in f1, dann in f2, dann in f3, wohingegen Skin B definiert sein könnte als: erst in f2, dann in f3 und erst dann in f1 nachschauen (und so weiter; je mehr Folder man hat, desto größer die kombinatorischen Möglichkeiten). Auf diese Weise kann man beispielsweise unterschiedliche Designs seiner Seite anbieten (etwa indem man unterschiedliche Style Sheets in die jeweiligen Folder legt), daher auch der Name.

    Aber das Konzept erlaubt mehr, als nur verschieden Ansichten vorzuhalten. Im Prinzip kann man damit multiples Objektverhalten vorsehen, soll heissen, ein Objekt kann in Reaktion auf ein und denselben Methodenaufruf unterschiedlich reagieren, je nach dem, welcher Skin gerade aktuell ist (und das könnte z.B. benutzerabhängig sein).

    Ein weiterer Vorteil des Skinnings ist, dass man sehr leicht vorgefertigte Methoden des Frameworks nach eigenen Bedürfnissen anpassen kann, ohne deren Quelltext anfassen zu müssen (das ist ein großer Vorteil bei der Systempflege). Das CMF macht hierzu die vorgefertigen Skinfolder als file system directory views in der ZODB (und damit dem ZMI, das letztlich ein through the web management Interface der ZODB darstellt) sichtbar. Navigiert man nun (via ZMI) in einen der Skinfolder und wählt man eine Methode aus, so kann man dann durch klicken des customize Knopfes eine lokale Kopie dieser Methode im custom Skinfolder erstellen. Diese Kopie liegt nun aber nicht im Filesystem, sondern in der ZODB und kann mit allen hier zur Verfügung stehenden Mittel bearbeitet werden. Da der custom Folder nun in der Regel in den Suchpfaden der Skins vor den standard Foldern plaziert ist, wird die eigene Methode nun wenn benötigt zuerst gefunden und somit angewandt. Man beachte, dass die Originalmethode hiervon vollkommen unberührt bleibt. Sie ist nach wie vor da und unverändert und sobald man seine eigene, angepasste Methode wieder löscht oder umbenennt, wird sie wieder Anwendung finden (sehr hilfreich, wenn man plötzlich feststellt, irgendetwas verkorkst zu haben).

  • Der ZCatalog

    Der ZCatalog wird benötigt, um in der ZODB suchen zu können. In Zope ohne CMF/Plone muss man sich den Katalog erstmal "selber bauen", während CMF und somit auch Plone einen vorkonfigurierten portal_catalog mitbringen. Der Katalog basiert auf den Konzepten von Indizes, Brains und Metadaten, die einem Anfänger in der Regel nicht vertraut sind, daher hier eine kurze Erläuterung:

    • Index: Bei der Formulierung einer Suche kann man den Katalog nur nach Werten in bestimmten Indizes fragen (man denke an ein Stichwortverzeichnis in einem Buch). Es gibt nun verschiedene Arten von Indizes, die sich in ihrer Funktionalität unterscheiden. So kann man beispielsweise über field indexes sortieren oder eine Bereichssuche (range search) durchführen wohingegen text indexes zwar keine Sortierung dafür aber Globbing (die Verwendung von Platzhaltersymbolen wie ? oder *) unterstützen.
    • brains: Der Katalog beinhaltet nicht die Objekte selbst (oder Kopien von ihnen), sondern eine Art Referenzobjekte, die in der Zopeterminologie brains oder catalog brains genannt werden. Brains verfügen über Methoden wie getObject() oder getURL(), um an das referenzierte Objekt oder seine URL zu gelangen. Darüberhinaus können Brains mit
    • Katalog-Metadaten ausgestattet werden, in denen ausgewählte Attributwerte (oder Resultate aus Methodenaufrufen) des original Objektes beim referenzierenden Brainobjekt in Kopie gehalten werden. Das hat den Vorteil, dass man in Anwendungen, die auf Suchanfragen aufbauen (wie nahezu alle Übersichten in einem Portal), die relevanten Informationen (Titel, Beschreibung, Thema, etc. des Objekts) zur Verfügung hat, ohne die Objekte selbst ansprechen zu müssen. Das ist wesentlich performanter als sich dann erst noch Zugriff auf potentiell sehr große Objekte verschaffen zu müssen. Welche Metadaten man für welche Objekttypen bereit hält, ist eine wichtige Designentscheidung und dabei muss man im wesentlichen Plattenplatz gegen Performance abwägen.

      Eine vertiefte Einführung in den ZCatalog und die ihm zugrunde liegenden Konzepte findet man unter http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/SearchingZCatalog.stx

  • Was das CMF zu Zope hinzufügt

    Zope selbst ist ein sehr allgemeines Framework, das vielseitige Anwendungen unterstützt (hauptsächlich im Bereich Web-Publikation, aber nicht ausschließlich; so kann die ZODB ganz allgemein von jeder Pythonapplikation verwendet werden). Das CMF erweitert Zope um Komponenten, die das Erstellen von web-basierten Content-Management-Systemen erleichtern. Dazu gehören Komponenten zur Registrierung und Verwaltung von Benutzern, der schon erwähnte Portalkatalog, das Skin-Tool, ein Workflow-System, eine "Fabrik" (das Types Tool zur Vereinheitlichung der Generation und Handhabung unterschiedlicher Inhaltstypen), sowie einige weitere.

  • Unterschiede zwischen CMF und Zope

    Um die Erweiterungen des CMF richtig nutzen zu können, sollte man manches in einer CMF- oder Plone-Site anders machen als in einer reinen Zope-Site. So ist es im allgemeinen nicht ratsam, Portalinhalte über das ZMI zu erzeugen oder zu bearbeiten, da so die "CMF-wrapper Methoden" umgangen werden, die dafür sorgen, dass andere Komponenten des Portals von den Änderungen bei Bedarf erfahren (hier sind vor allem der Katalog und die Workflow-Komponente zu nennen).

    Beispiel: Zur Erzeugung einer Instanz einer Inhaltsklasse des Portals (Dokument, Bild, File, etc.) sollte man invokeFactory verwenden - wie es aus der Inhaltsansicht (folder_content_view) bei Add (selected) erfolgt, anstatt den Konstruktor direkt aufzurufen (wie es durch das ZMI der Fall wäre). Invokefactory bringt über das Types Tool in Erfahrung, wie der jeweilige Typ zu generieren ist und initialisiert darüberhinaus den Workflow (mittels portal_workflow.notifyCreated(obj)) und meldet das Objekt beim Portalkatalog an (mittls obj.indexObject()). Ruft man nur den Konstruktor auf (via Add im ZMI), so unterbleiben diese weiteren Schritte.

Zope/CMF/Plone erweitern

Zusätzlich zum Developers Guide hat mir folgendes zu Beginn weitergeholfen:

Allgemein finden sich unter http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/collective/ viele interessante Erweiterungen für Plone (und es werden ständig mehr;-).

Zope/CMF/Plone Scripting

Mit Scripting meine ich hier, Aktionen, die der Administrator oder Benutzer über die Webschnittstelle ausführt, aus Programmen heraus auszuführen. Zu wissen, wie das geht, kann für vielerlei Anwendungen hilfreich seien, doch mangels Dokumentation ist es oft gar nicht so leicht, herauszufinden, wie man das macht. Für Zope selbst gibt es im Zopebuch einen Anhang, der die API (das Applikation Programmer Interface, eben das, was man hierzu braucht) beschreibt. Für CMF oder Plone gibt es eine API Dokumentation über die On-line Help-Funktion des ZMI, aber aufgrund der Komplexität des Systems, ist es gerade für Neulinge nicht ganz einfach, sich darin zurechtzufinden.

Wenn in den Mailinglisten die Frage nach der CMF/Plone-API-Dokumentation gestellt wird, habe ich auch schon mehr als einmal die Antwort "read the source" gegeben, nicht zuletzt, weil das meist tatsächlich die einzige Möglichkeit ist, weiterzukommen. Da Python Quelltext im allgememeinen durchaus lesbar ist, ist das auch halb so schlimm, wenn man sich erst einmal etwas eingearbeitet hat, aber am Anfang ist das durchaus abschreckend.

Was darüberhinaus meist fehlt, sind funktionierende Beispiele anhand derer man direkt sehen kann, wie man etwas konkret formulieren muss (nur allzu oft steckt der Teufel in syntaktischen Details).

Daher habe ich mit ScriptingCMF (http://www.neuroinf.de/LabTools) ein Tool geschrieben, das man als ausführbare Dokumentation bezeichnen könnte. ScriptingCMF besteht aus einem Pythonmodul (ScriptSite.py) und einem Pythonscript (rscript_site.py), sowie einer README Datei und einem Resourcenverzeichnis. Dem ganzen liegt die Idee zugrunde, quasi ein How-To zu schreiben, das auch ausgeführt werden kann und dabei genau das tut, was in dem How-To beschrieben wird.

Es gibt nun (mindestens) zwei qualitativ unterschiedliche Möglichkeiten, Zope-Sites aus Skripten heraus zu manipulieren, die ich hier einmal als intern oder lokal und extern oder remote bezeichnen möchte. Als internes Skript verstehe ich eines, das innerhalb von Zope ausgeführt werden muss. Ein solches findet sich in dem ScriptSite.py Modul, das in Zope als External Method angemeldet werden muss, und das dann über den Test-Tab ausgeführt werden kann. Als externes Skript verstehe ich eines, das an der Kommandozeile eines beliebigen Rechners, der Python versteht und an das Internet angeschlossen ist, ausgeführt werden kann. Ein solches ist rscript_site.py. Dieses Skript nutzt Pythons urllib, um mit dem (vom Skript zuvor erfragten) Server einer Zope-Site zu kommunizieren.

Man sollte also zunächst einmal die Quelltexte lesen und versuchen zu verstehen was dort steht, bevor man sie dann ausführt und sich (hoffentlich) davon überzeugen kann, dass die erwarteten Veränderungen auch tatsächlich eingetreten sind.

Zope debugen

Wennn man erst einmal begonnen hat für Zope zu entwickeln, wird man sicher früher oder später einen Debuger (oder eine integrierte Entwicklungsumgebung) haben wollen. Boa Constructor http://boa-constructor.sourceforge.net/ ist frei erhältlich und bietet recht guten Python Support.

Man kann aber Zope auch interaktiv in einer Python-Shell bei laufendem Betrieb analysieren. Wie das geht, ist hier beschrieben: http://www.zope.org/Members/klm/ZopeDebugging/ConversingWithZope

Zope optimieren

Ein Beispiel für ein etwas fortgeschritteneres Setup (eine Plone Site über einen high performance Zope cluster mit Authentifizierung via OpenLDAP) findet sich hier: http://matthardy.us/mywiki/HighPerformanceZope

Interoperabilität

(oder wie stelle ich eine Verbindung zu anderen Applikationen her?) Das CMF bringt ein syndication tool mit, das es ermöglicht, Verzeichnisinhalte in einem Standardformat (einem XML Dialekt namens RSS/RDF) verfügbar zu machen (sogenannte outbound Syndication). Das Einbeziehen von Inhalten anderer Sites, die dort in diesem Format angeboten werden, in die eigene Site (inbound Syndiction) erfordert dagegen die Installation zusätzlicher Module.

Web Services sind bislang kein Schwerpunkt in der Zope-Entwicklung, aber es gibt bereits einige Anwendungsbeispiele.

Created by dzugng
Last modified 09.04.2005 15:21