Benutzerspezifische Werkzeuge
Sie sind hier: Startseite Support Plone (Onlinebuch) Anhang A: Wichtige Konfigurationen und einige APIs
Die maximale Bildbreite kann wie folgt gewählt werden:

Anhang A: Wichtige Konfigurationen und einige APIs

Wichtige Konfigurationen und einige APIs

Dieser Anhang enthält einige der wichtigsten Konfigurationsmöglichkeiten bei der Entwicklung mit Zope, Plone und Python. Er enthält Informationen für Site-Entwickler und listet auch einige der nützlichsten APIs (Application Programming Interfaces) auf.

Einrichten Ihrer Umgebung

In den folgenden Abschnitten finden Sie Informationen über die Konfiguration Ihrer Entwicklungs- oder Produktionsumgebung, damit Sie diese optimal einrichten können. Wenn Sie viel mit Plone entwickeln, möchte ich Ihnen diese Einstellungen sehr empfehlen.

PYTHONPATH einrichten

Die Einrichtung von PYTHONPATH ist sehr nützlich, weil Sie dadurch sehr leicht auf die gesamte Zope-Funktionalität vom Python-Prompt aus zugreifen können. Sie können ganz leicht herausfinden, ob Sie diese Einstellung bereits verwenden. Versuchen Sie einfach, das Modul PageTemplate aus Products zu importieren. Wenn das noch nicht eingerichtet ist, werden Sie folgenden Fehler sehen:

$ python -c "import Products.PageTemplate"
Traceback (most recent call last):
  File "<string>", line 1, in ?
ImportError: No module named Products.PageTemplate
Unix, Linux und Mac OS X

Finden Sie zuerst das Produktverzeichnis Ihrer Zope-Installation (nicht die Instanzwurzel). Bei einer Standardinstallation liegt es unter /opt/Zope-2.7/lib/python. Unter Windows liegt es unter C:\Programme\Plone\Zope\lib\python. Wenn Python gestartet wird, liest es eine Umgebungsvariable namens PYTHONPATH, aus der es alle dort angegebenen Verzeichnisse in seinen Suchpfad für neue Module übernimmt. Das heißt, Sie müssen Ihr Verzeichnis zu dieser Variablen hinzufügen.

Das machen Sie mit dem Befehl export. Um also zu sehen, ob zu Beginn irgendetwas in PYTHONPATH enthalten ist, führen Sie Folgendes aus:

$ export | grep PYTHONPATH
declare -x PYTHONPATH="/home/andy/modules"

In meinem Fall habe ich bereits eine Umgebungsvariable namens PYTHONPATH, aber auf Ihrem Rechner haben Sie diese Einstellung möglicherweise nicht. Bei mir enthält sie einen Pfad zu einigen internen Modulen. Nun müssen Sie also Zope 2 zu diesem Pfad hinzufügen, z.B. so:

$ export PYTHONPATH="/opt/Zope-2.7/lib/python:$PYTHONPATH"

Ob das funktioniert hat, können Sie testen, indem Sie den folgenden Befehl wiederholen, wobei Sie darauf achten sollten, dass kein Fehler auftritt.

$ python -c "import Products.PageTemplate"
Windows

Unter Windows befindet sich das Zope-Produktverzeichnis in C:\Programme\Plone 2\Zope\lib\python. Wenn Python gestartet wird, liest es eine Umgebungsvariable namens PYTHONPATH, aus der es alle dort angegebenen Verzeichnisse in seinen Suchpfad für neue Module übernimmt. Das heißt, Sie müssen Ihr Verzeichnis zu dieser Variablen hinzufügen. Unter Windows fügen Sie eine Umgebungsvariable hinzu, indem Sie auf das Icon "Arbeitsplatz" rechtsklicken und Eigenschaften auswählen. Klicken Sie im Dialogfeld Systemeigenschaften auf den Reiter Erweitert, und klicken Sie dann unter Systemvariablen auf den Button Neu, wie in Abbildung A.1 zu sehen ist.

img/A-01.png

Abbildung A.1. Das Dialogfeld für die Umgebungsvariablen

Anschließend wird das Dialogfeld Systemvariablen geöffnet. Um eine Variable zu bearbeiten, wählen Sie eine aus der Liste und bearbeiten den Wert, wie in Abbildung A.2 gezeigt wird. Die Variable sollte PYTHONPATH heißen, und ihr Wert sollte der Ort sein, wo sich Ihr Plone befindet, z.B. C:\Programme\Plone 2\Zope\lib\python.

img/A-02.png

Abbildung A.2. Eine Variable hinzufügen

Nun sollten Sie die Import-Anweisung ganz normal ausführen können. Das können Sie von der Kommandozeile aus tun, oder Sie starten PythonWin und probieren dort den Import aus, wie in Abbildung A.3 demonstriert wird.

img/A-03.png

Abbildung A.3. Importieren in PythonWin

Ab jetzt können Sie nicht nur Produkte importieren, sondern Sie können auf der Kommandozeile auch import Zope ausführen, was Voraussetzung für viele Skripten und Werkzeuge in den fortgeschritteneren Kapiteln dieses Buchs ist.

Ausführung von Unittests einrichten

Plone enthält einige hundert Unittests, die eine hervorragende Methode darstellen, um zu überprüfen, ob Ihr Plone korrekt funktioniert. Die Plone-Unittests finden Sie in CMFPlone/tests. Wenn Sie mit Plone entwickeln, dann wäre es eine gute Idee, diese auf Ihrem Rechner einzurichten, damit Sie eigene Tests hinzufügen können. Um diese Tests auszuführen, benötigen Sie ZopeTestCase. In Zukunft wird das vermutlich ein Teil von Plone werden, aber im Moment müssen Sie das noch unter http://zope.org/Members/shh/ZopeTestCase herunterladen.

Die Installation ist etwas ungewöhnlich, Sie müssen das Paket erst auspacken und dann in das Verzeichnis lib/Python/Testing des Zope-Wurzelverzeichnisses kopieren. Unter Unix liegt es normalerweise in opt/Zope-2.7, während es unter Windows in C:\Programme\Plone 2\Zope liegt.

Als nächstes benötigen Sie ein Skript, das die Tests ausführt. Dazu schreibe ich normalerweise ein kleines Shell-Skript und kopiere es ins bin-Verzeichnis meiner Plone-Instanz. Dann kann ich einfach dieses Shell-Skript starten, um die Tests auszuführen. Unter Unix, wo sich meine Plone-Instanz unter /var/test befindet, sieht mein Skript wie folgt aus:

export SOFTWARE_HOME=/opt/Zope-2.7/lib/python
export INSTANCE_HOME=/var/test123

echo Testing CMFPlone...
cd $INSTANCE_HOME/Products/CMFPlone/tests
python2.3 runalltests.py

Unter Windows sieht das Äquivalent dazu so aus:

set SOFTWARE_HOME=C:\Programme\Plone 2\Zope
set INSTANCE_HOME=C:\Programme\Plone 2\Data

cd "C:\Programme\Plone 2\Data\Products\CMFPlone\tests"
"C:\Programme\Plone 2\Python\python.exe" runalltests.py

Die Ausgabe sollte ungefähr wie folgt aussehen:

[root@basil bin]# ./testAll.sh
Testing CMFPlone...
SOFTWARE_HOME: /opt/Zope-2.7/lib/python
INSTANCE_HOME: /opt/Zope-2.7/lib/python/Testing
Loading Zope, please stand by ... done (7.899s)
Installing CMFCore ... done (1.363s)
Installing CMFDefault ... done (0.713s)
Und so weiter...

Das Unittest-Framework ist eine hervorragende Grundlage für die Durchführung von Unittests bei eigenen Produkten. Wenn Sie Produkte oder allgemein Software für Plone entwickeln, dann sollten Sie idealerweise Unittests dafür schreiben. Die in Plone enthaltenen Unittests sind ein exzellentes Beispiel dafür, wie Sie das machen können.

Die Zope-Konfigurationsdatei

Die Zope-Konfigurationsdatei ist in einem Format namens ZConfig geschrieben. Weitere Informationen über ZConfig finden Sie unter http://www.zope.org/Members/fdrake/zconfig. Die Konfigurationsdatei hat den Namen zope.conf und befindet sich im etc-Verzeichnis Ihrer Zope-Installation. Manche Installationsprogramme erzeugen auch eine Datei namens plone.conf mit Plone-spezifischen Angaben.

Als Plattform für alle Plone 2-Installationen wird Zope 2.7 empfohlen. In dieser Version von Zope kam diese Datei zum ersten Mal vor. Davor wurden Parameter über die Kommandozeile an Zope übergeben.

In dieser Datei fangen alle Kommentare mit einem # an. In ZConfig definieren Sie Variablen, die später in dieser Konfigurationsdatei benutzt werden können. Dazu verwenden Sie eine Zeile im folgenden Format:

%define variablen-name variablen-wert

Folgende Zeilen sind Beispieldefinitionen aus meiner Konfigurationsdatei:

%define INSTANCE /var/test
%define ZOPE /opt/Zope-2.7

Diese Variablen benutzen Sie dann, indem Sie ihren Namen ein $ voranstellen, wie z.B. in $INSTANCE.

Tabelle A.1 enthält die gesamte Zope-Konfiguration für Version 2.0.1. Die Spalte Direktive enthält den Variablennamen in der Konfigurationsdatei. Die Spalte Beschreibung erklärt, was die Direktive bewirkt, und die Spalte Vorgabe gibt an, was passiert, wenn kein Wert für diese Variable gesetzt ist. In der Spalte Beispiel habe ich ein paar Beispiele als zusätzliche Hilfe zur Erklärung angegeben.

Tabelle A.1. Direktiven in der Zope-Konfigurationsdatei

Direktive Beschreibung Vorgabe Beispiel
instancehome Der Pfad zu den Dateien mit Daten, Produkten, dem Import-Verzeichnis und dem Extensions-Verzeichnis. Jede Zope-Instanz sollte eine solche Direktive haben. None /var/zope oder $INSTANCE
client home Das Verzeichnis, in dem die Dateien zur Prozessidentifikation von Zope liegen, z.B. die Prozess-ID-Datei Z2.pid. Von seinem Gebrauch wird abgeraten. Siehe stattdessen pid-filename. INSTANCE/ var $INSTANCE_HOME/var
path Name eines Verzeichnisses, das am Anfang von Pythons Modulsuchpfad eingefügt werden soll. Diese Direktive kann mehrfach verwendet werden. Da das zu spät sein kann, sollte lieber, wie vorher beschrieben, PYTHONPATH verändert werden. None path /home/pythonModules
products Name eines Verzeichnisses, das weitere Produkte enthält. Kann mehrfach verwendet werden. Jedes identifizierte Verzeichnis wird zum __path__ des Products-Pakets hinzugefügt. Ich muss vom Gebrauch abraten, da normalerweise ein instance home genügt. Es wurden auch schon Fehler in Plone wegen dieser Direktive gemeldet. None products /home/chrism/ projects/myproducts
environment Ein Abschnitt, in dem beliebige Schlüssel/Wert-Paare als Umgebungsvariablen definiert werden können, während Zope läuft. Es empfiehlt sich nicht, hier Systemvariablen wie PYTHONPATH zu setzen. Die meisten Startup-Skripten definieren für Sie solche Variablen. Deswegen wird vom Gebrauch abgeraten. None <environment> MY_PRODUCT_ENVVAR foobar</environemnt>
debug-mode Ein Schalter, der verschiedene Bereiche im Betrieb von Zope betrifft, die bei der Entwicklung mit Zope nützlich sind. Ich empfehle, alle Entwicklungsserver in diesem Modus zu betreiben. Manche Plone-Installationsprogramme schalten das standardmäßig evtl. aus Gründen der Performance aus. On debug-mode off
effective-user Wenn Sie Zope unter dem Benutzer root betreiben möchten, muss diese Direktive mit dem Namen oder der ID eines effektiven Benutzers angegeben werden, zu dem Zope mit suid umschaltet, nachdem die Server-Ports belegt sind. Funktioniert nur unter Unix und wenn Zope unter root gestartet wird. Sie können einen Benutzer namens zope erstellen und den effektiven Benutzer auf zope setzen, damit Zope garantiert unter diesem Benutzer läuft. Außerdem dürfen Sie dann Ports zwischen 21 und 80 belegen. None effective-user zope
enable-product- installation Wenn diese Direktive eingeschaltet ist, führt Zope eine Produkt-Installation beim Hochfahren durch (eine Registrierung von Python-Modulen in verschiedenen Produktverzeichnissen). Wenn man das ausschaltet, erfolgt das Hochfahren von Zope/ZEO eventuell schneller, kann aber auch dazu führen, dass Ihre Produktliste im Control Panel nicht mehr synchron mit dem Inhalt der Produktverzeichnisse ist. Ein enable-product- installation off
locale Das unterstützt die Internationalisierung, durch die Angabe eines Namens für ein Locale. Schauen Sie in die Dokumentation Ihres Betriebssystems für spezifische Informationen. None locale fr_FR
port-base Der auf Port-Nummern angewendete Offset bei der ZServer-Konfiguration. Wenn der http-server-Port gleich 8080 und port-base gleich 1000 ist, hört der HTTP-Server den Port 9080 ab. Das ist dann gut, wenn Sie mehrere Plone-Instanzen auf einem Rechner betreiben und schnell alle Port-Nummern ändern müssen. 0 1000
datetime-format Setzt diese Variable entweder auf us oder international, um das DateTime-Modul jeweils dazu zu zwingen, Datumsstrings mit den Formaten MM-DD-JJ bzw. DD-MM-JJ zu parsen. Der Vorgabewert lautet us. us datetime-format international
zserver-threads Gibt die Anzahl der Threads an, mit denen Zopes Webserver ZServer Anfragen bedient. Auf den meisten Sites führt ein hoher Wert an dieser Stelle nicht zu besserer Performance. Dazu verwende man ZEO und Caching. 4 zserver-threads 10
python-check- interval Ein Integer für das "Check-Intervall" des Python-Interpreters, das bestimmt, wie oft der Interpreter periodische Aufgaben durchführt, z.B. das Umschalten von Threads und die Signalbehandler. Auf den meisten Sites führt ein hoher Wert an dieser Stelle nicht zu besserer Performance. 500 python-check- interval 1000
zserver-read- only-mode Wenn eingeschaltet, erzeugt Zope keine Log- und Prozess-ID-(PID-)Dateien. Zugriffs- und Fehler-Logdateien werden auf die Standardausgabe ausgegeben. off zserver-read-only-mode on
pid-filename Der Pfad der Datei, in der die PIDs von Zope geschrieben werden. Der Vorgabewert lautet client-home/Z2.pid. CLIENT_HOME/ Z2.pid pid-filename /home/chrism/ projects/sessions/var/ Z2.pid
lock-filename Der Pfad der "Lock-Datei", die von Zope im laufenden Betrieb gesperrt wird. CLIENT_HOME/ Z2.lock lock-filename/home/chrism/ projects/sessions/var/ Z2.lock
mime-types Hiermit erfährt Zope von weiteren mime-types-Dateien, die es laden soll. Die Dateien haben das gleiche Format wie die von Apache. Diese Einstellung darf mehrmals in einer Konfigurationsdatei vorkommen. None mime-types $INSTANCE/etc mime-types
structured- text-header- level Setzt den Vorgabewert des HTML-Header- Levels in Dokumenten in strukturiertem Text. Standardwert ist 3, d.h., die obersten Header werden mit dem Tag <h3> erzeugt. Leider ignoriert CMF diesen Wert noch, was irgendwann noch geändert werden muss. 3 structured-text-header- lebvel 1
rest-input- encoding Gibt die Eingabekodierung von Dokumenten in restrukturiertem Text an, z.B. als utf-8, iso-8859-15 oder eine andere gültige und von Python erkannte Kodierung. Der Vorgabewert ist der Ihrer Python-Version. System- vorgabewert rest-input-encoding iso-8859-15
rest-output- encoding Gibt die Ausgabekodierung von Dokumenten in restrukturiertem Text an, z.B. utf-8, iso-8859-15 oder eine andere gültige und von Python erkannte Kodierung. Der Vorgabewert ist der Ihrer Python-Version. System- vorgabewert rest-output-encoding iso-8859-15
cgi-environment Ein Abschnitt, in dem Benutzer beliebige Schlüssel/Wert-Paare für CGI-Umgebungsvariablen angeben können. None <cgi-environment> HTTPS_SERVER Foobar Server 1.0 HTTPS_PORT 443 </cgi-environment>
dns-server Gibt die IP-Adresse Ihres Domain Name System-(DNS-)Servers an, durch den in Zopes Zugriffslogdateien aufgelöste Hostnamen geschrieben werden. Wenn Sie das einschalten, werden Verzögerungen durch DNS-Anfragen Ihre Site verlangsamen. None dns-server 127.0.0.1
ip-address Gibt die IP-Adresse vor, auf denen die verschiedenen Server-Protokolle ihre Anfragen erwarten. Ohne einen Wert an dieser Stelle hört Zope alle verfügbaren IP-Adressen auf dem Rechner ab. None ip-address 127.0.0.1
http-realm Der HTTP-Header-Wert für Realm, den Zope in dieser Instanz ausgibt. Dieser Wert taucht oftmals in Dialogfeldern zur einfachen Authentifizierung auf. Zope Plone
automatically- quote-dtml- request-data Setzen Sie diese Direktive auf off, um das "Autoquoting" von implizit erhaltenen REQUEST- Daten in DTML-Code zu unterbinden, der ein < in <dtml-var>- Konstrukten enthält. Sonst werden alle implizit von REQUEST in DTML erhaltenen Daten (im Gegensatz zum direkten Zugriff mit REQUEST.einVarName), die ein < enthalten, mit HTML-Quotes versehen, wenn sie mit <dtml-var> oder &dtml- interpoliert werden. Das verringert die Wahrscheinlichkeit, dass Programmierer ihre Sites für clientseitige Trojaner-Attacken offen lassen. on automatically-quote-dtml request-data on
trusted-proxy Gibt einen oder mehrere Hostnamen oder IP-Adressen an. None trusted-proxy www.example.com
publisher- profile-file Gibt eine Datei im Dateisystem an, durch die Zopes Profiling-Fähigkeiten aktiviert werden. Weitere Informationen dazu finden Sie unter dem Profiling-Reiter im ZMI. Sollte in Produktion nicht gesetzt werden, da dadurch der Code wesentlich langsamer ausgeführt wird als normal. None publisher-profile-file $INSTANCE/var/profile.dat
security- policy- implementation Die normale Sicherheitsmaschinerie von Zope ist in C implementiert. Die Python-Version können Sie verwenden, wenn Sie hier python setzen. Diese ist langsamer, bietet mit VerboseSecurity aber wichtige Informationen. C security-policy- implementation python
skip- authentication- checking Setzen Sie hier on, wenn Zope Prüfungen bei der Authentifizierung von Servern auslassen soll, die nur anonyme Inhalte anbieten. off skip-authentication- checking on
skip- ownership- checking Setzen Sie hier on, wenn Zope Besitz-Prüfungen auslassen soll, wenn Code "über das Web" ausgeführt werden soll. Das ist standardmäßig eingeschaltet, um Sicherheitsprobleme mit Trojanern zu verhindern, wobei Benutzer mit niedrigen Privilegien solche mit höheren Privilegien dazu bringen können, gefährlichen Code auszuführen. on skip-ownership-checking off
maximum-number- of-session- objects Ein Integer-Wert als "maximale Anzahl von Unterobjekten" des transienten Objekt-Containers in /temp/folder/session_data 1000 maximum-number-of-session- objects 1000
session-add- notify-script- path Ein optionaler Zope-Pfadname eines aufrufbaren Objekts, das als "Skript beim Addieren von Objekten" des transienten Objekt-Containers aufgerufen werden soll, der beim Hochfahren im Ordner /temp_folder erzeugt wird. Für den Einsatz mit Sessions. ungesetzt session-add-notify-script- path /scripts/add_notifier
session-delete- notify-script- path Ein optionaler Zope-Pfadname eines aufrufbaren Objekts, das als "Skript beim Löschen von Objekten" des transienten Objekt-Containers aufgerufen werden soll, der beim Hochfahren im Ordner /temp_folder erzeugt wird. Für den Einsatz mit Sessions. ungesetzt session-delete-notify- script-path * */scripts/add_notifier
session- timeout- minutes Ein Integer-Wert für die Anzahl der Minuten, die als "Datenobjekt-Timeout" des transienten Objekt-Containers /temp/folder/session_data benutzt werden soll. 20 session-timeout-minutes 30
suppress-all access-rules- Wenn auf on gesetzt, werden in Ihrer Zope-Site keine Zugriffsregeln ausgeführt. Nützlich, wenn Sie sich selbst aus einem bestimmten Teil Ihrer Site aussperren, indem Sie eine falsche Zugriffsregel einstellen. off suppress-all-access-rules on
suppress-all site-roots Wenn auf on gesetzt, sind in Ihrer Zope-Site keine Site-Roots aktiviert. Nützlich, wenn Sie sich selbst aus einem bestimmten Teil Ihrer Site aussperren, indem Sie eine falsche Site-Root schreiben. off suppress-all-site-roots on
database- quota-size Die obere Grenze als Anzahl von Bytes für die Größe der FileStorage-basierten Zope-Datenbank. Nachdem diese Zahl erreicht wird, können keine weiteren Objekte zur Datenbank hinzugefügt werden. None database-quota-size 1000000
read-only- database Bewirkt, dass die FileStorage-basierte Zope-Datenbank ZODB nur lesend geöffnet wird. Andere Dateien, z.B. Logdateien, können geschrieben werden. off read-only-database on
zeo-client-name Wenn Sie einen persistenten ZEO-Client-Cache haben möchten, der den Cache-Inhalt über Neustarts von ClientStorage hinweg aufbewahrt, müssen Sie einen zeo-client-name definieren. Wenn Sie sonst ZEO benutzen, wird der Client-Cache in temporären Dateien gespeichert, die gelöscht werden, wenn ClientStorage beendet wird. Der Wert von zeo-client-name ist eindeutig für die erzeugten Cache-Dateien, falls diese Zope-Instanz ein ZEO-Client ist. off zeo-client-name on
logger Dieser Bereich sollte einen oder mehrere logger-Abschnitte mit den Namen access, event und trace definieren. Der access- Logger loggt Zugriffe auf den Zope- Server fest, der event-Logger loggt Informationen zu Zope-Events, und der trace-Logger loggt detaillierte Informationen zu Serveranfragen (nur für die Fehlersuche). Jeder Logger-Abschnitt darf ein Name/Wert-Paar eines Levels enthalten, mit dem der Grad an Logging-Details angegeben wird. Der Vorgabe-Level lautet INFO. Erlaubte Werte hierfür sind CRITICAL, ERROR, WARN, INFO, DEBUG und ALL. Jeder Logger-Abschnitt darf weiterhin ein oder mehrere handler- Abschnitte enthalten, die den Typ des Log-Handlers angeben. Es gibt fünf Handler-Typen: logfile, syslog, win32-eventlog, http-handler und email-notifier. Jeder hat seine eigenen erlaubten Unterschlüssel, die gewisse Aspekte des Handlers bestimmen. In allen Handler- Abschnitten kann auch format (der Format-String der Log-Einträge), dateformat (der Format-String der Datums-Strings) und level angegeben werden. Letzterer hat die gleiche Semantik wie wie der übergeordnete Logger-Level, überschreibt aber den Level-Logger des Handlers, in dem er definiert ist. Der access-Log schreibt auf dem Level INFO in die Datei <instance home/log /Z2.log>, der event- Log auf dem Level INFO in das Datei- Log, und der trace-Log wird nirgendwo geschrieben. <eventlog> `` level ALL`` `` <logfile>`` `` path $INSTANCE/log/`` event.log `` level INFO`` `` </logfile>`` </eventlog> <logger access> `` level WARN`` `` <logfile>`` `` path $INSTANCE/log/`` Z2.log `` format %(message)s`` `` </logfile>`` </logger>
warnfilter In diesem Abschnitt können Sie Warnungsfilter angeben. Folgende Schlüssel gelten in einem warnfilter-Abschnitt, action: einer der Strings error, ignore, always, default, module und once; message: ein String mit einem regulären Ausdruck, mit dem die Warnung übereinstimmen muss (unabhängig von Groß-/Kleinschreibung); category: ein Python-Klassenname mit Punkten (muss eine Unterklasse von Warning sein), von der die Warnungskategorie eine Unterklasse sein muss, damit die Übereinstimmung erfolgen kann; module: ein String mit einem regulären Ausdruck, der mit dem Modulnamen übereinstimmen muss (unabhängig von der Schreibweise); lineno: ein Integer, der mit der Nummer der Zeile übereinstimmen muss, in der die Warnung aufgetreten ist, oder 0, was mit allen Zeilennummern übereinstimmt. None <warnfilter> action ignore category exceptions. DeprecationWarning </warnfilter>
max-listen- sockets Die maximale Anzahl von Sockets, die ZServer versucht zu öffnen, um einkommende Verbindungen zu bedienen. 1000 max-listen-sockets 500
servers Eine Reihe von Abschnitten, mit denen die verschiedenen ZServer von Zope angegeben werden können. Es können sieben Servertypen definiert werden: http-server, ftp-server, webdav-source-server, persistent-cgi, fast-cgi, monitor-server und icp-server. Wenn keine Server definiert werden, werden die vorgegebenen Server benutzt. Ports können entweder in einer einfachen Form angegeben werden (80) oder in komplexer Form inklusive Hostname (127.0.0.1:80). Wenn der Hostname weggelassen wird, wird als Hostname default-ip-address benutzt. Port-Nummern werden durch die Einstellung in port-base mit dem Standardwert 8000 verschoben. In Ihrer Plone-Installation kann das verändert worden sein, damit eine erste Installation einfacher wird. HTTP-Server auf Port 8080 und FTP auf 8021 <http-server> `` # valid key is`` "address" and `` ``"force-connection- close" `` address 8080`` `` # force-connection-`` close" on </http-server> <ftp-server> `` # valid key is`` "address" `` address 8021`` </ftp-server>
database Der database-Abschnitt erlaubt die Angabe eigener Datenbank- und Speicher- typen. Es kann mehr als ein zodb_db-Abschnitt definiert werden. Die Werte im Speicher werden von den Werten in dem jeweiligen Datenbank-Client gesetzt. Siehe Bsp. ((argh..... siehe unten))
<zodb_db main>
  # Main FileStorage database
  <filestorage>
    path $INSTANCE/var/Data.fs
  </filestorage>
  mount-point /
<zodb_db>
<zodb_db temporary>
  # Temporary database database (for sessions)
  <temporarystorage>
    name temporary storage for sessioning
  </temporarystorage>
  mount-point /temp_folder
  container-class Products.TemporaryFolder.TemporaryContainer
<zodb_db>

Von allen Konfigurationen sind die letzten paar (Datenbank, Server und Logger) Direktiven in einer einfachen XML-artigen Syntax. Wenn Sie mit der Apache-Protokolldatei arbeiten, wird Ihnen dieses Format bekannt vorkommen. Diese Direktiven können Sie auch mehrfach anwenden. So besteht eine häufige Konfiguration von Installationsprogrammen auf dem Mac oder unter Windows darin, HTTP-Verbindungen auf zwei Ports, 80 und 8080, durchzuführen. Das machen Sie wie folgt:

<http-server>
  address 8080
</http-server>

<http-server>
  address 80
</http-server>

Regeln zur Textformatierung

Plone verfügt mit External Editor und Epoz über zwei exzellente Werkzeuge zur Bearbeitung von HTML. In Zope und Python werden allerdings zwei Formate von einfachem Text häufig verwendet: strukturierter Text und restrukturierter Text. Da die beiden genannten Editoren qualitativ sehr gut sind, glaube ich, dass Sie diese Formate nicht benötigen werden. Aber wenn Sie mit Zope oder Plone entwickeln werden, werden Ihnen diese Formate sehr wahrscheinlich irgendwann begegnen.

Beide Formate versuchen, ähnliche Dinge zu machen: Sie bieten ein System zur Auszeichnung von einfachem Text an, aus dem sie HTML generieren. Das zielt auf Entwickler ab, die gern mit einfachem Text arbeiten und daran gewöhnt sind, die aber den Aufwand scheuen, selbst HTML zu produzieren.

Strukturierter Text

Es folgt eine Darstellung, wie sie bereits in einem älteren Artikel erschienen ist. Sie finden ihn online unter http://plone.org/documentation-old/howto/UsingStructuredText. Im folgenden Abschnitt ist die Einrückung des Textes im Code von entscheidender Bedeutung dafür, wie der Text dargestellt wird.

Einfache Formatierung

Das Grundkonzept von strukturiertem Text baut auf einem Absatz auf. Das Beispiel

Das ist der erste Absatz.

Das ist der zweite Absatz.

wird zu folgendem HTML umgewandelt:

<p>Das ist der erste Absatz.</p>
<p>Das ist der zweite Absatz.</p>

Die Whitespaces zwischen Elementen in strukturiertem Text sind von Bedeutung. In diesem Fall bewirkt eine Leerzeile zwischen den beiden anderen, dass ein neuer Absatz anfängt. Das ist intuitiv leicht zu verstehen. In E-Mails z.B. werden Absätze auch mit Leerzeilen voneinander getrennt. Für Hervorhebungen im Text benutzt strukturierter Text eine andere Konvention, nämlich Sternchen. Beispiel:

Das ist der *erste* Absatz.

Das ist der **zweite** Absatz.

In HTML entstehen daraus die Tags em und strong:

<p>Das ist der <em>erste</em> Absatz.</p>
<p>Das ist der <strong>zweite</strong> Absatz.</p>

Auch dieses Muster kann man häufig in E-Mails beobachten. Einige andere häufig benutzte Muster werden ebenfalls unterstützt, z.B. Verweise auf einen Jargon-Begriff:

Wenn Sie 'STX' lesen, wissen Sie, dass es eine
Abkürzung für 'strukturierter Text' ist.

Die HTML-Ausgabe hierzu sieht wie folgt aus:

<p>Wenn Sie <code>STX</code> lesen, wissen Sie, dass es eine
Abkürzung für <code>strukturierter Text</code> ist.</p>
Einrückung verwenden

Der vorangegangene Abschnitt handelte von Textkonventionen, mit denen eine Semantik verbunden ist. Bei der Verarbeitung des strukturierten Textes werden aus dieser Semantik bestimmte HTML-Tags erzeugt. Die Einrückung von strukturiertem Text hat ebenfalls eine Semantik. Die grundlegendste hat mit dem Konzept von Überschriften in HTML zu tun. Im folgenden Beispiel steht die Einrückung für eine outline-artige Struktur.

Einrückung verwenden
  Der vorangegangene Abschnitt handelte von Textkonventionen, mit denen eine 
Semantik verbunden ist. Bei der Verarbeitung des strukturierten Textes werden 
aus dieser Semantik bestimmte HTML-Tags erzeugt.

Daraus wird folgender HTML-Code produziert:

<h1>Einrückung verwenden</h1>

<p>Der vorangegangene Abschnitt handelte von Textkonventionen, mit denen eine 
Semantik verbunden ist. Bei der Verarbeitung des strukturierten Textes werden 
aus dieser Semantik bestimmte HTML-Tags erzeugt.</p>

In der Einrückung war also eine Bedeutung enthalten, der Absatz war nämlich der Überschrift untergeordnet, und diese Beziehung wird in HTML ausgedrückt. Tatsächlich kann eine solche Outline-Beziehung wie folgt fortgesetzt werden:

Einrückung verwenden
  
  Der vorangegangene Abschnitt handelte von Textkonventionen, mit denen eine 
Semantik verbunden ist. Bei der Verarbeitung des strukturierten Textes werden 
aus dieser Semantik bestimmte HTML-Tags erzeugt.

  Grundlagen der Einrückung
  
    In diesem Abschnitt werden wir die Grundlagen der Einrückung untersuchen...

Daraus wird folgeder HTML-Code produziert:

<h1>Einrückung verwenden</h1>

<p>Der vorangegangene Abschnitt handelte von Textkonventionen, mit denen eine 
Semantik verbunden ist. Bei der Verarbeitung des strukturierten Textes werden 
aus dieser Semantik bestimmte HTML-Tags erzeugt.</p>

<h2>Grundlagen der Einrückung</h2>
  
<p>In diesem Abschnitt werden wir die Grundlagen der Einrückung untersuchen...</p>
Listen und Listeneinträge

Listen werden in strukturiertem Text ebenfalls unterstützt, darunter ungeordnete, geordnete und beschreibende Listen. Die Konvention zu ungeordneten Listen ist ein häufig benutztes Muster in der Kommunikation mit Texten.

In HTML gibt es drei verschiedene Arten von Listen:

  • ungeordnete Listen
  • geordnete Listen
  • beschreibende Listen

In strukturiertem Text dürfen Sie Listenelemente mit den vorangestellten Symbolen *, o und - auszeichnen. Das obige Beispiel produziert folgenden HTML-Code:

<p>In HTML gibt es drei verschiedene Arten von Listen:</p>
<ul>
<li><p>ungeordnete Listen</p></li>
<li><p>geordnete Listen</p></li>
<li><p>beschreibende Listen</p></li>
</ul>

Die Konvention hinter geordneten Listen sieht in strukturiertem Text wie folgt aus:

In HTML gibt es drei verschiedene Arten von Listen:

1. ungeordnete Listen
2. geordnete Listen
3. beschreibende Listen

Dabei wird Folgendes produziert:

<p>In HTML gibt es drei verschiedene Arten von Listen:</p>
<ol>
<li><p>ungeordnete Listen</p></li>
<li><p>geordnete Listen</p></li>
<li><p>beschreibende Listen</p></li>
</ol>

Beschreibende Listen lassen sich genauso leicht mit doppelten Spiegelstrichen angeben. Beispiel:

geordnete Listen -- HTML-Viewer wandeln die Listenelemente in eine nummerierte Folge um

beschreibende Listen -- werden normalerweise für Definitionslisten wie in Glossaren verwendet

Daraus wird folgender HTML-Code:

<dl>
<dt>geordnete Listen</dt>
<dd><p>HTML-Viewer wandeln die Listenelemente in eine nummerierte Folge um</p></dd>
<dt>beschreibende Listen</dt>
<dd><p>werden normalerweise für Definitionslisten wie in Glossaren verwendet</p></dd>
</dl>
Beispiel-Code

System Message: INFO/1 (<string>, line 764)

Possible title underline, too short for the title. Treating it as ordinary text because it's so short.

Autoren von strukturiertem Text können eine einfache Konvention benutzen, um die mit der Semantik eines code-Tags in HTML verbundene unproportionale Darstellung zu erreichen. Der Code

Sobald Sie das Dialogfeld sehen, klicken Sie auf den Button 'OK'.

wird zum Beispiel mit folgendem HTML-Code dargestellt:

<p>Sobald Sie das Dialogfeld sehen, klicken Sie
auf den Button <code>OK</code>.</p>

Manchmal benötigen Sie aber auch längere Code-Passagen. Was, wenn Sie z.B. eine Python-Funktion mitten in einem Artikel über Python dokumentieren möchten? Einen solchen Code-Block geben Sie an, indem Sie einen Absatz mit zwei Doppelpunkten beenden (::) und den oder die folgenden Absätze einrücken. Aus

In diesem Beispiel wandeln wir Menschenjahre in Hundejahre um:

def hundeJahre(alter):
    """Wandle Menschenjahre in Hundejahre um."""
    return alter * 7

wird dieser HTML-Code erzeugt:

<p>In diesem Beispiel wandeln wir Menschenjahre in Hundejahre um:</p>

<pre>
def hundeJahre(alter):
    """Wandle Menschenjahre in Hundejahre um."""
    return alter * 7
</pre>

Bei dieser Konvention, ein :: am Ende eines Absatzes mit einem eingerückten Block zu kombinieren, wird nicht nur eine Code-Semantik angewendet, sondern der eingerückte Block wird auch geschützt. Das heißt, die Schnipsel mit strukturiertem Text bzw. HTML in diesem Artikel werden nicht angetastet und bleiben in ihrer rohen Darstellung. Im folgenden Beispiel werden die Zeichen für kleiner-als, größer-als und das kaufmännische Und geschützt:

Hier ist ein HTML-Beispiel:

<html>
<p>Dies ist eine Seite zu Hunden & Katzen.</p>
<html>

was das folgenden HTML-Code produziert:

<p>Hier ist ein HTML-Beispiel:</p>

<pre>
  <html>
    <p>Dies ist eine Seite zu Hunden & Katzen.</p>
  <html>
</pre>

Restrukturierter Text

Restrukturierter Text (im Englischen oft als reStructured Text geschrieben) ist eine neuere Version von strukturiertem Text, die einige Probleme beheben soll, die manche Leute mit älteren Versionen hatten. Strukturierter Text versagt nicht nur beim Thema Internationalisierung, sondern produziert ungültige Auszeichnungen. Außerdem ist seine Syntax manchmal etwas schwer verständlich.

Das neue restrukturierte Textformat ist zu einem der Standards für die Dokumentation von Python-Code geworden und wird auch im Docutils-Projekt verwendet. Die Online-Dokumentation ist so gut, dass ich Ihnen ohne Vorbehalte empfehlen möchte, sie unter http://docutils.sourceforge.net/rst.html zu lesen.

Es folgt einiges an Material, das von Richard Jones geschrieben wurde.

Einleitung

Als Grundeinheit wird ein Absatz erkannt, also ein Textbrocken, der mit Leerzeilen abgetrennt ist, wobei eine Leerzeile ausreicht. Absätze müssen alle die gleiche Einrückungstiefe haben, d.h., sie müssen links gleich weit weg vom Rand sein. Eingerückte Absätze erscheinen als eingerückte Zitate. Aus dem Code

Dies ist ein Absatz, ein recht kurzer noch dazu.

  Aus diesem Absatz wird ein eingerückter Textblock,
  in dem oftmals ein anderer Text zitiert wird.
  
Und noch ein Absatz.

wird folgende Ausgabe:

<blockquote>
  <p>Dies ist ein Absatz, ein recht kurzer noch dazu.</p>
    <blockquote>
      Aus diesem Absatz wird ein eingerückter Textblock,
      in dem oftmals ein anderer Text zitiert wird.
    </blockquote>
  <p>Und noch ein Absatz.</p>
</blockquote>
Textstile

In Absätzen und anderen Textteilen können Sie Text zusätzlich mit *kursiv* als kursiv oder mit **fett** als fett auszeichnen.

Wenn Sie möchten, dass etwas nichtproportional erscheint, verwenden Sie doppelte Rückanführungszeichen: ``. Beachten Sie, dass innerhalb dieser Anführungszeichen nichts angetastet wird, d.h. Sternchen usw. bleiben unverändert.

Falls Sie ein "besonderes" Zeichen im Text verwenden möchten, können Sie das normalerweise tun, denn restrukturierter Text ist ziemlich clever. Das Sternchen z.B. funktioniert prima. Wenn Sie wirklich einmal Text mit Sternchen drumherum haben möchten, der nicht kursiv gesetzt werden soll, müssen Sie angeben, dass das Sternchen keine Bedeutung hat. Das machen Sie, indem Sie wie folgt einen Rückschrägstrich davor setzen:

\*

Oder Sie umschließen ihn mit doppelten Rückanführungszeichen wie folgt:

``\*``
Listen

Es gibt drei verschiedene Sorten von Listen: geordnete, ungeordnete und beschreibende Listen. Bei allen dreien dürfen Sie beliebig viele Absätze, Unterlisten usw. verwenden, solange der linke Absatzrand genauso weit eingerückt ist wie die erste Textzeile im Listenelement.

Listen stehen immer am Anfang eines neuen Absatzes, d.h., sie müssen nach einer Leerzeile stehen. Beginnen Sie eine Zeile mit einer Zahl oder einem Buchstaben, gefolgt von einem Punkt, mit einer runden Klammer danach oder insgesamt in runden Klammern, was immer Ihnen lieber ist. Alle Beispiele in Listing A.1 werden erkannt.

Listing A.1. Beispiele für Punkte

1. Zahlen

A. Großbuchstaben
   auch über mehrere Zeilen
   
   sogar mit zwei Absätzen darin!
   
a. Kleinbuchstaben

   3. mit einer Unterliste, die mit
      einer anderen Zahl beginnt
   4. aber die Zahlen sollten schon 
      die richtige Reihenfolge haben!
   
I. Große römische Zahlen

i. Kleine römische Zahlen

(1) wieder Zahlen

1) und nochmal

Listing A.2 zeigt das Ergebnis, aber beachten Sie, dass die Stile für die verschiedenen Aufzählungslisten nicht von allen Browsern unterstützt werden, d.h., Sie können eventuell nicht den ganzen Effekt sehen.

Listing A.2. Beispielliste

<ol class="arabic simple">
<li>Zahlen</li>
</ol>
<ol class="upperalpha">
<li><p class="first">Großbuchstaben
auch über mehrere Zeilen</p>
<p>sogar mit zwei Absätzen darin!</p>
</li>
</ol>
<ol class="loweralpha simple">
<li>Kleinbuchstaben<ol class="arabic" start="3">
<li>mit einer Unterliste, die mit 
einer anderen Zahl beginnt</li>
<li>aber die Zahlen sollten schon 
die richtige Reihenfolge haben!</li>
</ol>
</li>
</ol>
<ol class="upperroman simple">
<li>Große römische Zahlen</li>
</ol>
<ol class="lowerroman simple">
<li>Kleine römische Zahlen</li>
</ol>
<ol class="arabic simple">
<li>wieder Zahlen</li>
</ol>
<ol class="arabic simple">
<li>und nochmal</li>
</ol>

Statt wie bei geordneten Listen können Sie Listeneinträge auch mit einem Punkt davor haben, indem Sie entweder -, + oder * wie folgt verwenden:

* ein Punkt mit "*"

  - eine Unterliste mit "-"

    + eine andere Unterliste

  - ein weiterer Eintrag

was folgenden Code erzeugt:

<ul class="simple">
<li>ein Punkt mit &quot;*&quot;<ul>
<li>eine Unterliste mit &quot;-&quot;<ul>
<li>eine andere Unterliste</li>
</ul>
</li>
<li>ein weiterer Eintrag</li>
</ul>
</li>
</ul>

Anders als die beiden vorausgegangenen Listenarten bestehen beschreibende Listen aus einem Begriff und seiner Definition. Das Format einer solchen Liste lautet wie folgt:

*Was*
  Beschreibende Listen verbinden einen Begriff mit einer Definition.

*Wie*
  Der Begriff besteht aus einem einzeiligen Satz, und die Definition 
  besteht aus einem oder mehreren Absätzen, die relativ zum Begriff eingerückt 
  sind. Zwischen Begriff und Definition sind keine Leerzeilen erlaubt.

Dadurch wird der folgende Code erzeugt:

<blockquote>
<dl class="docutils">
<dt><em>Was</em></dt>
<dd>Beschreibende Listen verbinden einen Begriff mit einer Definition.</dd>
<dt><em>Wie</em></dt>
<dd>Der Begriff besteht aus einem einzeiligen Satz, und die Definition 
besteht aus einem oder mehreren Absätzen, die relativ zum Begriff eingerückt 
sind. Zwischen Begriff und Definition sind keine Leerzeilen erlaubt.</dd>
</dl>
</blockquote>
Vorformatierung (Code-Beispiele)

Um einfach einen Brocken Text einzufügen, der unter keinen Umständen jemals angetastet werden soll, beenden Sie den vorhergehenden Absatz mit ::. Der vorformatierte Block gilt als beendet, wenn der Text wieder die Einrückungsebene vor dem vorformatierten Block erreicht. Beispiel:

Beispiel::
        
      Leerräume, Zeilenenden, Leerzeilen und alle Arten
      von Auszeichnungen, z.B. *das* oder \das, werden 
      in solchen literalen Blöcken erhalten.
    Schau mal, eine Ebene rauf
    (aber nicht weit genug).
  
Nicht mehr im Beispiel.

Dadurch wird der folgende Code erzeugt:

<div class="document">
<p>Beispiel:</p>
<pre class="literal-block">
  Leerräume, Zeilenenden, Leerzeilen und alle Arten
  von Auszeichnungen, z.B. *das* oder \das, werden 
  in solchen literalen Blöcken erhalten.
Schau mal, eine Ebene rauf
(aber nicht weit genug).
</pre>
<p>Nicht mehr im Beispiel.</p>
</div>

Beachten Sie, dass ein Absatz, der nur aus :: besteht, in der Ausgabe nicht erscheint. Beispiel:

::

  Das ist vorformatierter Text, und der 
  letzte Absatz mit "*::*" wird entfernt.

Das erzeugt den folgenden Code:

<pre class="literal-block">
  Das ist vorformatierter Text, und der 
  letzte Absatz mit "::" wird entfernt.
</pre>
Abschnitte

Mit Überschriften können Sie längere Texte in Abschnitte untergliedern. Sie bestehen aus einer einzelnen Textzeile mit nur einer Schmuckzeile danach oder einer davor und danach. Diese Zeilen bestehen aus Minuszeichen (-----), Gleichheitszeichen (=====), Tilden (~~~~~) oder einem beliebigen nichtalphanumerischen Zeichen, das Ihnen gefällt:

- = ` : ' " ~ ^ _ * + # < >

Eine Schmuckzeile nur unter einer Überschrift ist verschieden von einer, die vor und nach einer Überschrift verwendet wird, aber sonst aus dem gleichen Zeichen besteht. Diese Zeile davor bzw. danach muss mindestens so lang sein wie die Textzeile. Diese Zeilen sollten Sie konsistent verwenden, da alle Überschriften mit der gleichen Schmuckzeile sich auf der gleichen Ebene befinden. Beispiel:

Kapitel 1 Titel
===============

Abschnitt 1.1 Titel
-------------------

Unterabschnitt 1.1.1 Titel
~~~~~~~~~~~~~~~~~~~~~~~~~~

Abschnitt 1.2 Titel
-------------------

Kapitel 2 Titel
===============

Daraus wird der folgende Code, der hier in vereinfachtem Pseudo-XML angegeben ist:

<section>
  <title>
    Kapitel 1 Titel
  <section>
    <title>
      Abschnitt 1.1 Titel
    <section>
      <title>
        Unterabschnitt 1.1.1 Titel
  <section>
    <title>
      Abschnitt 1.2 Titel
<section>
  <title>
    Kapitel 2 Titel

Pseudo-XML verwendet eine Einrückung zur Darstellung der Schachtelung und enthält keine schließenden Tags. Hierbei kann man nicht wie bei den anderen Beispielen eine echte Ausgabe zeigen, weil Abschnitte in Blöcken nicht vorkommen dürfen. Vergleichen Sie als konkretes Beispiel den Quelltext zum englischen Original dieses Textes unter http://docutils.sourceforge.net/docs/rst/quickstart.html mit der erzeugten Ausgabe.

Beachten Sie, dass dabei die Abschnittsüberschriften als Ziele von Links fungieren, wenn man ihren Namen benutzt. Um einen Link zur Überschrift Listen zu erstellen, schreiben Sie Listen_. Wenn in der Überschrift ein Leerzeichen vorkommt, wie in Restrukturierter Text, müssen Sie die Überschrift wie folgt in Anführungszeichen setzen: `Restrukturierter Text`_.

Bilder

Um ein Bild in Ihrem Dokument einzubinden, verwenden Sie die Direktive image. Zum Beispiel wird der folgende Code:

.. image:: images/biohazard.png

wie folgt zu HTML umgewandelt:

<div class="image">
<img alt="images/biohazard.png" src="images/biohazard.png" />
</div>

Der Teil images/biohazard.png bezeichnet den Dateinamen des Bildes, das an dieser Stelle im Dokument erscheinen soll. Beim Bildformat (Format, Größe usw.) gibt es keine Einschränkungen. Wenn das Bild in HTML-Code erscheinen soll und Sie noch weitere Angaben dazu machen möchten, können Sie das wie folgt tun:

.. image:: images/biohazard.png
     :height: 100
     :width: 200
     :scale: 50
     :alt: Alternativtext

Verschiedenes

Es folgen ein paar Tipps, die für Plone-Entwickler hilfreich sein könnten.

Alle globalen Definitionen im Haupt-Template

Tabelle A.2 listet alle globalen Definitionen im Haupt-Template auf, zusammen mit dem Code, der sie definiert, und einer Beschreibung. Wie immer gilt, dass dies keine starre Liste ist, sondern eine, die sich im Laufe der Zeit vermutlich verändern wird. Daher empfehle ich, einen Blick in den Quellcode zu werfen. Diese Zusammenstellung stammt aus CMFPlone/skins/main_template/globale_defines.pt.

Diese Definitionen werden vorwiegend in Page Templates benutzt und stellen nützliche Abkürzungen dar. Beispiel:

<a href="" tal:attributes="portal_url">Url to the portal</a>

Tabelle A.2. Globale Definitionen im Haupt-Template

Name Code Beschreibung
utool nocall:here/portal_url; Das Werkzeug portal_url.
portal utool/getPortalObject; Das eigentliche Portal-Objekt.
portal_object nocall:portal; Ein weiterer Name für das Portal.
portal_url utool; Ein weiterer Name für das Werkzeug portal_url.
mtool nocall:portal/ portal_membership; Das Werkzeug membership.
gtool nocall:portal/ portal_groups | nothing; Das Werkzeug groups, falls vorhanden.
dtool nocall:portal/ portal_groupdata | nothing; Das Werkzeug groups data tool, falls vorhanden.
atool nocall:portal/ portal_actions; Das Werkzeug portal_actions.
aitool nocall:portal/ portal_actionicons | nothing; Das Werkzeug portal_actionicons.
putils nocall:portal/ plone_utils; Das Werkzeug utils.
wtool nocall:portal/ portal_workflow; Das Werkzeug portal_workflow.
ifacetool nocall:portal/ plone_interface | nothing; Das Werkzeug portal_interface, falls vorhanden.
portal_title portal_object/Title; Der Portaltitel.
object_title here/Title; here/Title; Der Titel des aktuellen Objekts.
member mtool/ getAuthenticatedMember; Das aktuelle Mitglied.
checkPermission nocall: mtool/checkPermission; Die Funktion checkPermission des membership-Werkzeugs.
membersfolder mtool/getMembersFolder; Der Members-Ordner des aktuellen Mitglieds, falls vorhanden.
isAnon mtool/isAnonymousUser; Boolescher Wert, falls der Benutzer anonym ist.
actions python: portal. portal_actions. listFilteredActionsFor (here); Die Aktionen am aktuellen Ort.
keyed_actions python: portal. keyFilteredActions (actions); Die Liste aller Aktionen mit einer ID.
user_actions actions/user; Aktionen für den Benutzer.
workflow_actions actions/workflow; Workflow-Aktionen.
folder_actions actions/folder; Ordner-Aktionen.
global_actions actions/global; Globale Aktionen.
portal_tabs actions/portal_tabs| nothing; Portalreiter-Aktionen.
wf_state python:wtool.getInfoFor (here,'review_state', None); Workflow-Zustand des aktuellen Objekts.
portal_properties portal/ portal_properties; Das Objekt portal_properties.
site_properties portal_properties/ site_properties; Das Objekt site_properties.
ztu modules/ZTUtils; Das Modul ZTUtils, ein nützliches Hilfsmodul.
actions options/actions| actions; Die über das Template explizit übergebenen Aktionen.
wf_actions workflow_actions; Ein weiterer Name für Workflow-Aktionen.
isFolder python:here. getTypeInfo().getId() in site_properties. use_folder_tabs; Boolescher Wert, falls der Kontext ein Ordner ist.
template_id options/template_id | template/getId | | nothing; Die ID des aktuellen Templates.
slots_mapping options/slots_mapping| here/prepare_slots| nothing; Die Slots-Abbildung.
Iterator python:modules ['Products.CMFPlone'] .IndexIterator; Ein Iterator, verwendet in Templates.
tabindex python:Iterator (pos=30000); Der Tabindex-Iterator für Formulare.
here_url here/absolute_url; Aktuelle absolute_url.
sl slots_mapping/left; Abbildung für linke Slots.
sr slots_mapping/right; Abbildung für rechte Slots.
default_language site_properties/ default_language| nothing; Standardsprache in site_properties.
allowed_types here/getAllowedTypes; Erlaubte Inhaltstypen in diesem Ordner.
is_editable python:here. showEditableBorder( template_id= template_id, allowed_types= allowed_types, actions=actions ); Gibt an, ob das aktuelle Objekt bearbeitet werden kann und eine grüne Umrandung haben soll.

API zu DateTime

Ich habe im ganzen Buch schon DateTime-Objekte verwendet, ohne ihre API zu erklären. In Plone werden solche Objekte sehr häufig verwendet, z.B. bei der Suche mit Datumsangaben oder bei deren Darstellung.

Um ein DateTime-Objekt zu erstellen, übergeben Sie einen String, der auch als Datumsangabe interpretiert werden kann:

>>> from DateTime import DateTime
>>> d = DateTime('2004/12/01')
>>> d.month()
12

Auf diesen Datumsobjekten können Sie dann gewisse Operationen ausführen. Um z.B. die Differenz zwischen zwei Datumsobjekten zu bilden, machen Sie Folgendes:

>>> x = DateTime('2004/11/02')
>>> z = DateTime('2004/11/30')
>>> z - x
28.0

Dieser Abschnitt enthält nur die Kurzfassung des APIs. Die vollständige Dokumentation finden Sie im DateTime-Verzeichnis Ihrer Zope-Installation.

DateTime-Objekte repräsentieren Zeitpunkte und bieten eine Schnittstelle zu ihrer Darstellung, ohne dass dabei der absolute Wert des Objekts verändert wird.

Sie können DateTime-Objekte aus einer Vielzahl von Strings oder aus numerischen Daten erzeugen, oder Sie erzeugen sie aus anderen DateTime-Objekten. Sie können ihre Darstellung an viele Zeitzonen anpassen, und Sie können DateTime-Objekte für eine gegebene Zeitzone erstellen.

Außerdem verfügen DateTime-Objekte zum Teil über ein zahlenähnliches Verhalten:

  • Zwei DateTime-Objekte können voneinander subtrahiert werden, um die Zeitdauer in Tagen dazwischen zu beschreiben.
  • Ein DateTime-Objekt kann zu einer positiven oder negativen Zahl addiert werden, um ein neues DateTime-Objekt plus der angegebenen Zahl von Tagen zu erzeugen.
  • Eine positive oder negative Zahl kann zu einem DateTime-Objekt addiert werden, um ein neues DateTime-Objekt plus der angegebenen Zahl von Tagen zu erzeugen.
  • Eine positive oder negative Zahl kann von einem DateTime-Objekt subtrahiert werden, um ein neues DateTime-Objekt minus der angegebenen Zahl von Tagen zu erzeugen.

Sie können DateTime-Objekte zu der Anzahl von Tagen seit dem 1. Januar 1901 im Integer-, Long- oder Float-Typ konvertieren, indem Sie die normalen Funktionen int, long und float verwenden. Beachten Sie aber, dass diese Funktionen die Anzahl der Tage in der Greenwich Mean Time (GMT) angeben und nicht in der lokalen Zeitzone Ihres Rechners. Außerdem bieten DateTime-Objekte auch einen Zugriff auf ihren Wert in einem Float-Format, der mit dem time-Modul in Python verwendet werden kann, vorausgesetzt, dass dieser Wert im Zeitraum des auf der Epoche basierenden time-Moduls liegt.

Ein DateTime-Objekt sollte als unveränderlich betrachtet werden. Alle Umwandlungs- und andere Operationen geben ein neues DateTime-Objekt zurück und verändern nicht das gegebene Objekt.

Um ein DateTime-Objekt zu erzeugen, übergeben Sie einen String, der ein gültiges Datum beschreibt. Wenn Sie kein Argument übergeben, wird ein Objekt für den aktuellen Zeitpunkt erzeugt. Der Wert eines DateTime-Objekts wird immer in absoluter UTC-Zeit verwaltet und wird im Kontext einer Zeitzone dargestellt, die auf den Argumenten basiert, die bei der Erzeugung des Objekts angegeben wurden.

Tabelle A.3 beschreibt alle Methoden, die bei einem DateTime-Objekt aufgerufen werden können.

Tabelle A.3 Verfügbare Methoden auf einem DateTime-Objekt

Methode Beschreibung
aMonth() Gibt den abgekürzten Monatsnamen zurück.
pCommon() Gibt eine String-Darstellung des Objektwerts im Format Jan. 13, 2005 1:41 pm zurück.
minute() Gibt die Minute zurück.
isLeapYear() Gibt zurück, ob das aktuelle Jahr (im Kontext der Zeitzone des Objekts) ein Schaltjahr ist.
pMonth() Gibt den (mit Punkt) abgekürzten Monatsnamen zurück.
DayOfWeek() Kompatibilität: siehe Day().
Day_() Kompatibilität: siehe pDay().
isCurrentDay() Gibt im Kontext der Zeitzone dieses Objekts zurück, ob dieses Objekt einen Zeitpunkt am heutigen Tag darstellt.
Mon() Kompatibilität: siehe aMonth().
hour() Gibt die Stunde in 24-Stunden-Darstellung zurück.
Date() Gibt den Datums-String zu dem Objekt zurück.
aCommonZ() Gibt eine String-Darstellung des Objektwerts im Format Jan 13, 2005 1:40 pm GMT+1 zurück.
fCommonZ() Gibt eine String-Darstellung des Objektwerts im Format January 13, 2005 1:42 pm GMT+1 zurück.
isCurrentYear() Gibt im Kontext der Zeitzone dieses Objekts zurück, ob dieses Objekt einen Zeitpunkt im laufenden Jahr darstellt.
AMPMMinutes() Gibt den Zeit-String für ein Objekt ohne Sekunden mit Angabe von am/pm zurück.
dd() Gibt den Tag als String mit zwei Ziffern zurück.
TimeMinutes() Gibt den Zeit-String für ein Objekt ohne Sekunden in 24-Stunden-Darstellung zurück.
h_24() Gibt die Stunde in 24-Stunden-Darstellung zurück.
isPast() Gibt zurück, ob dieses Objekt einen Zeitpunkt vor dem Zeitpunkt dieses Aufrufs darstellt.
dow() Gibt den Wochentag als Integer zurück, wobei Sonntag gleich 0 ist.
isFuture() Gibt zurück, ob dieses Objekt einen Zeitpunkt nach dem Zeitpunkt dieses Aufrufs darstellt.
pCommonZ() Gibt eine String-Darstellung des Objektwerts im Format Jan. 13, 2005 2:01 pm GMT+1 zurück.
timezone() Gibt die Zeitzone des Objekts zurück.
h_12() Gibt die Stunde in 12-Stunden-Darstellung zurück.
PreciseTime() Gibt eine genaue String-Darstellung des Objekts zurück.
isCurrentMinute() Gibt im Kontext der Zeitzone dieses Objekts zurück, ob dieses Objekt einen Zeitpunkt in der laufenden Minute darstellt.
rfc822() Gibt den Zeitpunkt im Format RFC 822 zurück.
equalTo(t) Vergleicht dieses DateTime-Objekt mit einem anderen DateTime-Objekt oder einer Fließkommazahl, wie sie Pythons time-Modul zurückgibt. Gibt zurück, ob das Objekt einen Zeitpunkt beschreibt, der identisch mit dem angegebenen Objekt ist.
yy() Gibt das Kalenderjahr als String mit zwei Ziffern zurück.
mm() Gibt den Monat als String mit zwei Ziffern zurück.
Mon_() Kompatibilität: siehe pMonth().
toZone(z) Gibt ein DateTime-Objekt mit dem aktuellen Wert in der angegebenen Zeitzone zurück.
earliestTime() Gibt im Kontext der Zeitzone des Objekts ein neues DateTime-Objekt zurück, das den frühestmöglichen Zeitpunkt darstellt (in ganzen Sekunden), der immer noch auf den Tag des aktuellen Objekts fällt.
aDay() Gibt den abgekürzten Wochentag zurück.
dayOfYear() Gibt Kontext der Zeitzone des Objekts den Tag des Jahres zurück.
latestTime() Gibt im Kontext der Zeitzone des Objekts ein neues DateTime-Objekt zurück, das den spätestmöglichen Zeitpunkt darstellt (in ganzen Sekunden), der immer noch auf den Tag des aktuellen Objekts fällt.
notEqualTo(t) Vergleicht dieses DateTime-Objekt mit einem anderen DateTime-Objekt oder einer Fließkommazahl, wie sie Pythons time-Modul zurückgibt. Gibt zurück, ob das Objekt einen Zeitpunkt beschreibt, der verschieden vom angegebenen Objekt ist.
PreciseAMPM() Gibt eine genaue String-Darstellung des Objekts mit Angabe von am/pm zurück.
day() Gibt den Tag als ganze Zahl zurück.
timeTime() Gibt den Zeitpunkt als Fließkommazahl in UTC zurück, dem Format, das Python im time-Modul verwendet. Beachten Sie, dass man mit DateTime Zeitpunkte erstellen kann, die keine Entsprechung im Modul time haben, und in solchen Fällen wird der Fehler DateTimeError ausgelöst. Im Allgemeinen muss der Wert eines DateTime-Objekts zwischen dem 1. Januar 1970 (oder der Epoche auf Ihrem lokalen Rechner) und dem 1. Januar 2038 liegen, um einen gültigen Wert im Stil von time.time() zu erzeugen.
ampm() Gibt den passenden Zeitzusatz (am bzw. pm) zurück.
greaterThan(t) Vergleicht dieses DateTime-Objekt mit einem anderen DateTime-Objekt oder einer Fließkommazahl, wie sie z.B. von Pythons time-Modul erzeugt wird. Gibt zurück, ob das Objekt einen Zeitpunkt darstellt, der größer als das angegebene Objekt ist.
month() Gibt den Monat des Objekts als ganze Zahl zurück.
AMPM() Gibt den Zeit-String zu einem Objekt auf die nächste Sekunde genau zurück.
second() Gibt die Sekunde zurück.
parts() Gibt ein Tupel mit dem Kalenderjahr, Monat, Tag, der Stunde, Minute, Sekunde und Zeitzone des Objekts zurück.
greaterThanEqualTo(t) Vergleicht dieses DateTime-Objekt mit einem anderen DateTime-Objekt oder einer Fließkommazahl, wie sie z.B. von Pythons time-Modul erzeugt wird. Gibt zurück, ob das Objekt einen Zeitpunkt darstellt, der größer oder gleich dem angegebenen Objekt ist.
lessThanEqualTo(t) Vergleicht dieses DateTime-Objekt mit einem anderen DateTime-Objekt oder einer Fließkommazahl, wie sie z.B. von Pythons time-Modul erzeugt wird. Gibt zurück, ob das Objekt einen Zeitpunkt darstellt, der kleiner oder gleich dem angegebenen Objekt ist.
isCurrentHour() Gibt im Kontext der Zeitzone des Objekts zurück, ob dieses Objekt einen Zeitpunkt darstellt, der in die laufende Stunde fällt.
aCommon() Gibt eine String-Darstellung des Objektwertes im Format Jan 13, 2005 4:22 pm zurück.
dow_1() Gibt den Wochentag als ganze Zahl zurück, wobei, anders als bei der Methode dow, Sonntag gleich 1 ist.
Day() Gibt den vollen Namen des Wochentages zurück.
fCommon() Gibt eine String-Darstellung des Objektwertes im Format January 13, 2005 4:29 pm zurück.
Month() Gibt den vollen Monatsnamen zurück.
isCurrentMonth() Gibt im Kontext der Zeitzone des Objekts zurück, ob dieses Objekt einen Zeitpunkt darstellt, der in den laufenden Monat fällt.
year() Gibt das Kalenderjahr des Objekts zurück.
lessThan(t) Vergleicht dieses DateTime-Objekt mit einem anderen DateTime-Objekt oder einer Fließkommazahl, wie sie z.B. von Pythons time-Modul erzeugt wird. Gibt zurück, ob das Objekt einen Zeitpunkt darstellt, der kleiner als das angegebene Objekt ist.
Time() Gibt den Zeit-String für ein Objekt bis auf die nächste Sekunde genau zurück.
pDay() Gibt den (mit Punkt) abgekürzten Namen des Wochentages zurück.

Tabelle A.4 beschreibt alle eingebauten Methoden von DateTime-Objekten.

Tabelle A.4. Eingebaute Methoden von DateTime-Objekten

Methode Beschreibung
`dateTime` Wandelt ein DateTime-Objekt in einen String um, der wie ein Python-Ausdruck aussieht.
str(dateTime) Wandelt ein DateTime-Objekt in einen String um.
cmp(dateTime, other) Vergleicht ein DateTime-Objekt mit einem anderen oder mit einer Fließkommazahl, wie time.time() sie zurückgibt.
hash(dateTime) Berechnet den Hash-Wert eines DateTime-Objekts.

Tabelle A.5. beschreibt generische Dienste, die DateTime unterstützt.

Tabelle A.5. Generische DateTime-Funktionen

Methode Beschreibung
dateTime + anderes Ein DateTime-Objekt darf zu einer Zahl addiert werden und umgekehrt. Zwei DateTime-Objekte können aber nicht addiert werden.
dateTime - anderes Von einem DateTime-Objekt kann man entweder ein anderes DateTime-Objekt oder eine Zahl subtrahieren, aber ein DateTime-Objekt kann nicht von einer Zahl subtrahiert werden.
anderes + dateTime Addiert dateTime zu anderes. Ein DateTime-Objekt kann zu einer Zahl addiert werden und umgekehrt, aber zwei DateTime-Objekte können nicht addiert werden.
int(dateTime) Wandelt in eine Integer-Anzahl von Tagen seit dem 1. Januar 1901 (GMT) um.
long(dateTime) Wandelt in eine Long-Anzahl von Tagen seit dem 1. Januar 1901 (GMT) um.
float(dateTime) Wandelt in eine Float-Anzahl von Tagen seit dem 1. Januar 1901 (GMT) um.

Workflows in Python schreiben

Dieser Abschnitt behandelt die API zum Schreiben eines Workflows in Python, damit Sie nicht über das Web entwickeln müssen. Die folgenden Abschnitte enthalten eine verkürzte Liste der Methoden, die Sie benötigen, um einen Workflow zu erstellen. Um eine umfassende Liste zu erhalten, müssen Sie den Quellcode lesen, den Sie im Verzeichnis Products/DCWorkflow Ihrer Plone-Instanz finden.

Das Schreiben eines Workflows beginnt mit dem Erstellen einer Definition. Diese kann man wie folgt importieren:

from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition

Erzeugen Sie eine neue Instanz dieser Definition, und geben Sie ihr eine ID:

wf = DCWorkflowDefinition(id)

Nun haben Sie einen Workflow, den Sie manipulieren können. Im Folgenden ist wf die Workflow-Definition, die ich gerade erzeugt habe.

Zustände

Zustände verfügen über die folgenden Methoden:

  • addState(Id): Fügt einen Zustand mit der gegebenen ID hinzu. Zustände müssen Sie erst hinzufügen, bevor Sie sie manipulieren können.
  • setInitialState(Id): Setzt den Ausgangszustand für diesen Workflow.
  • setProperties([key=value,...]): Eine Reihe von Schlüssel/Wert-Paaren, die auf Eigenschaften eines Zustands abgebildet werden. Um z.B. die Übergänge auf Veröffentlichen und Zurückweisen zu setzen, verwenden Sie setProperties(transitions=('publish', 'reject'))..
  • setPermission(recht, aquirieren, (rolle, [rolle...])): Der Name des Rechts, ob akquirieren aktiviert ist oder nicht (ein boolescher Wert) und dann ein Tupel aller Rollen, für die das gilt.

Um auf diese Methoden zuzugreifen, verwenden Sie das states-Objekt im Workflow-Objekt. Verwenden Sie z.B. wf.states.addState('new').

Übergänge

Übergänge verfügen über die folgenden Methoden:

  • addTransition(id): Fügt einen Übergang mit der gegebenen ID hinzu. Übergänge müssen Sie erst hinzufügen, bevor Sie sie manipulieren können.
  • setProperties([key=value,...]): Eine Reihe von Schlüssel/Wert-Paaren, die auf Eigenschaften eines Übergangs abgebildet werden.

Um auf diese Methoden zuzugreifen, verwenden Sie das transitions-Objekt im Workflow-Objekt. Verwenden Sie z.B. wf.transitions.addTransition('reject').

Variablen

Variablen verfügen über die folgenden Methoden:

  • addVariable(id): Fügt eine Variable mit der gegebenen ID hinzu. Variablen müssen Sie erst hinzufügen, bevor Sie sie manipulieren können.
  • setStateVar(id): Setzt den Variablennamen, der normalerweise review_state ist.
  • setProperties([key=value,...]): Eine Reihe von Schlüssel/Wert-Paaren, die auf Eigenschaften einer Variablen abgebildet werden.

Um auf diese Methoden zuzugreifen verwenden Sie das variables-Objekt im Workflow-Objekt. Verwenden Sie z.B. wf.transitions.addVariable('action').

Sonstige

Worklists verhalten sich hier wie Übergänge, Variablen und Zustände. Um eine Worklist hinzuzufügen, rufen Sie addWorklist auf. Eine weitere nützliche Methode besteht darin, Rechte zu der Liste der verwalteten Rechte für den Workflow hinzuzufügen. Das bewerkstelligt man mit der Methode addManagedPermission(permission name).


Andy McKay: Plone. Addison-Wesley 2005
Diese online Version wurde mit Hilfe des 'PloneBookDE' Produkts von docs.neuroinf.de/products erstellt.
Es wurde zuletzt von
ctheune am 30.04.2006 14:15 aus der local Quelle via
/tmp/plonebook/PloneBook/de/ aktualisiert.