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.
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.
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.
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
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>
Hyperlinks
Die vorangegangenen Abschnitte konzentrierten sich auf verschiedene Arten, mit üblichen Textkonventionen eine Präsentationssemantik in HTML zu erzielen. Aber das Web besteht nicht nur aus Text. Verbindungen von Wörtern und Sätzen mit weiteren Informationen sowie die Einbindung von Bildern sind ebenso wichtig. Daher werden Hyperlinks und Bild-Tags auch im strukturierten Textformat unterstützt.
Beginnen wir z.B. mit einem einfachen Hyperlink. Wenn Sie z.B den folgenden Absatz über Python in strukturiertem Text haben:
Weitere Informationen zu Python finden Sie auf der "Python-Website":http://www.python.org.
wird daraus Folgendes in HTML:
<p>Weitere Informationen zu Python finden Sie auf der <a href="http://www.python.org">Python-Website</a>.
Die Konvention dahinter ist ziemlich einfach:
- Der Verweistext wird in Anführungszeichen gesetzt.
- Dem zweiten Anführungszeichen folgen ein Doppelpunkt und eine URL.
- Nach der URL dürfen Interpunktionszeichen stehen.
Zu dieser Basiskonvention gibt es eine Reihe von Varianten, damit auch relative, mailto- und Bild-URLs verwendet werden können.
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 "*"<ul> <li>eine Unterliste mit "-"<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
Es wurde zuletzt von loesch am 2006-01-11 13:38 aus der fallback Quelle aktualisiert.


