Programmierrichtlinien für Zope ------------------------------- (C) netEstate GmbH, www.netestate.de 1. Mandantenfähigkeit des Zope-Servers Dem Zope-Server ist im Normalfall ein Apache-Server vorgeschaltet, der alle oder bestimmte Pfade transparent auf den Zope-Server weiterleitet. Damit auf einem Zope-Server die Inhalte mehrerer Webserver gehostet werden können, sind alle Inhalte eines Webservers unterhalb eines Verzeichnisses im Root-Folder von Zope unterzubringen, das nach dem primären Namen des Webservers benannt ist. In diesem Verzeichnis - dem sogenannten Startverzeichnis - liegen alle sprach- und projektunabhängigen Objekte. 2. Unterteilung nach Projekten und Sprachen Nach Möglichkeit sollte dann pro Projekt ein Verzeichnis angelegt werden. In diesem liegen wiederum sprachunabhängige Objekte des Projektes wie Python-Skripten und Sql-Abfragen. Darunter wird für jede Sprache ein Verzeichnis mit dem ISO-Ländercode als Namen eingerichtet, in dem sprachabhängige Objekte liegen. Für Englisch ist "En" zu verwenden. In jedem Sprachverzeichnis wird ein Python-Skript "Sprache" mit dem Inhalt "return container.id" eingerichtet. Potentiell sprachabhängige Felder in Datenbanken enden mit einem Underscore ('_') gefolgt vom Code der jeweiligen Sprache - auch wenn bei der ersten Implementierung nur eine Sprache verwendet wird. Alternativ können verschiedene Sprachen auch über mehrere Datensätze eingegeben werden, deren jeweilige Sprache über ein entsprechendes Feld 'sprache' mit dem Sprachcode festgelegt wird. Soweit als möglich sollten die SQL-Abfragen - nicht die DTML-Templates - die Unterscheidung der Sprachen vornehmen, indem sie potentiell sprachabhängige Felder so: select feldname_ as feldname from tabelle und potentiell sprachabhängige Datensätze so: select feldname from tabelle where sprache='' abfragen. Der Webmaster muss beim Anlegen einer neuen Sprache im Idealfall nur das Verzeichnis für die vorhandene Sprache in das Verzeichnis für die neue Sprache kopieren und alle statischen Inhalte übersetzen. 3. Suchmaschinenoptimierung Bei Seiten mit Suchmaschinenrelevanten Inhalten (dies sind fast alle Seiten!) werden Parameter nur über die URL mit der Traversal-Technik für Z-SQL-Methoden übergeben. Beispiel: /Projekt/Sprache/HoleDatensatz/Parameter1/Wert1/Parameter2/Wert2/Template Hier wird das DTML-Document "Template" auf das Ergebnis der SQL-Abfrage HoleDatensatz(Parameter1=Wert1,Parameter2=Wert2) angewendet. Achtung: Die SQL-Methode HoleDatensatz muß dazu nicht im Verzeichnis Sprache liegen. Da sie gemäß der Richtlinien sprachunabhängig ist, sollte Sie im Verzeichnis Projekt liegen. Bei SQL-Methoden mit nur einem Parameter kann im Reiter Advanced das "simple Traversal" aktiviert werden: /Projekt/Sprache/HoleDatensatz/Wert1/Template Hier hat HoleDatensatz nur einen Parameter, dessen Name nicht genannt werden muß. Da manche Suchmaschinen URLs mit vielen / schlechter werten, werden auf manchen Websites alle URLs per URL-Rewriting umgeschrieben. Die zu verwendende URL kann dann aus der normalen URL über folgendes Verfahren gewonnen werden: -Alle / im Pfad sind durch _ zu ersetzen -Dem Pfad wird /rw_ vorangestellt, wobei die Anzahl der / im Pfad ist -Es wird .htm an den Pfad angehängt Aus /Projekt/Sprache/HoleDatensatz/Wert1/Template wird dadurch /rw_5_Projekt_Sprache_HoleDatensatz_Wert1_Template.htm 4. Modularisierung durch "Überschreiben" von DTML-Methoden und Properties Variable Bestandteile der Website werden in DTML-Methoden und Properties abgelegt und an zentraler Stelle (z.B. SeitenKopf,SeitenFuss) mit eingebunden. Die Defaultversion des Bestandteils wird als Property oder DTML-Methode des Startverzeichnisses definiert und in einzelnen Unterverzeichnissen bei Bedarf durch erneutes Anlegen "überschrieben". Kandidaten für DTML-Methoden sind veränderliche Bestandteile der Navigation. Als Properties werden häufig folgende Informationen gespeichert (gängige Namen der entsprechenden Properties in Klammern): -HTML-Title (htmltitel) -Metatags (meta_description,meta_keywords,meta_robots) -IVW-Codes (ivwCode) -IDs von Bannerplätzen für die Generierung von Adserver-Tags (placementID_) Wird ein Template auf verschiedene Datensätze einer Datenbanktabelle angewendet, um verschiedene Webseiten zu erzeugen, müssen die sonst in Properties gespeicherten Informationen manchmal aus der Datenbank geholt werden. Hierzu sollte die Property Name an zentraler Stelle nicht mit , sondern mit eingebunden sein. HoleName ist ein Python-Skript mit folgendem Inhalt: wert=getattr(context,'Namedb',None) if not wert: wert=context.Name return wert Definiert eine per URL-Traversal-Technik aufgerufene SQL-Abfrage das Feld Namedb, so wird dadurch der Wert dieses Feldes anstatt des Wertes der Property Name verwendet. 5. index_html Bei Verwendung von DTML-Templates mit dem Namen index_html fügt Zope automatisch unerwünschte Base-Tags der Form ein. Dies kann verhindert werden durch 6. Verlinkung von Seiten und Bildern Es sollten immer absolute Pfade verwendet werden (mit / beginnend). 7. Bilder Binden Sie Bilder immer mit IMG-Tags und nicht mit ein. Projektunabhängige Bilder liegen im Verzeichnis images des Startverzeichnisses. Projektbezogene Bilder liegen im Verzeichnis images des Projektordners. Sprachabhängige Bilder liegen im Verzeichnis images des Sprachverzeichnisses. Ist doch einmal die Verwendung von nötig, so ist folgendes zu beachten: Defaultmäßig erzeugt Zope aus ein IMG-Tag mit kompletter URL des Zope-Servers. Dieses Verhalten ist bei vorgeschaltetem Apache nicht erwünscht, weswegen es das Zope-Produkt RelativeURL gibt, welches die verwendete Funktion absolute_url dahingehend abändert, dass defaultmäßig ein absoluter Pfad ohne Servername ausgegeben wird. 8. Formulare Formulare haben grundsätzlich folgenden Aufbau: Formularname ist passend zu wählen und sollte auf der Website eindeutig sein. Die DTML-Methode Formular ist wie folgt aufzubauen (Beispiel für input, select, radio, checkbox und textarea):
FEHLER: checked type="radio" name="feld3" value="Wert1"> checked type="radio" name="feld3" value="Wert2"> checked type="checkbox" name="feld4" value="Wert">
Das zu erstellende Python-Skript PruefeFormular prüft alle Eingaben und liefert bei Korrektheit '' oder eine Fehlermeldung zurück. Bei einer mehrsprachigen Website sollte die Fehlermeldung über eine Funktion FehlerMeldung(fehlercode) aus einer mehrsprachigen Datenbanktabelle geholt werden. Die optionale Python-Funktion HoleDefaultDaten speichert eventuelle Defaultwerte im durch die Funktion SpeichereFormularDaten angelegten Dictionary der aktuellen Session. 9. Konventionen für Bezeichner von Python und Zope -Es sind deutsche Begriffe ohne Umlaute zu verwenden -Variablen und Properties Erster Buchstabe klein, ggf. jeder erste Buchstabe eines Teilwortes groß Beispiel: frame1Aktiv oder frame1aktiv -Klassen, Methoden, Funktionen, Dokumente Wie Variablen und Properties, aber hier mit großem Anfangsbuchstaben Beispiel: SeitenKopf oder Seitenkopf -SQL-Tabellen- und Feldnamen Immer klein 10. Escape-Funktionen für dynamische Werte Dynamische Werte werden im Normalfall mit &dtml-bezeichner; in einem DTML-Template für HTML-Seiten eingefügt. Dies ist gleichbedeutend mit Sofern neben html_quote weitere Attribute notwendig sind, kann Nur in abgesprochenen Ausnahmefällen darf auf html_quote verzichtet werden, so daß im dynamischen Wert eventuell enthaltener HTML-Markup auch zur Geltung kommt. Python-Skripten müssen dynamisch eingefügte Werte immer mit CgiEscape escapen, welches die gleiche Funktion wie html_quote hat. Für den Aufbau dynamischer Links ist in DTML das Attribut url_quote und in Python die Funktion QuotePlus zu verwenden. Bei Z-SQL-Methoden sind dynamische Werte immer mit einzufügen. Davon ausgenommern ist der Bezeichner "Sprache" für die aktuelle Sprache. 11. ZODB Conflict Errors und MySQL Bei hoher last kann durch ZODB Conflict Errors ein Request bis zu drei Aufrufe des entsprechenden Objekts verursachen. Wenn die entsprechenden Datenbanktabellen keine Transaktionen unterstützen (z.B. MyISAM bei MySQL), werden Datenbankänderungen bis zu dreimal ausgeführt. Es ist Aufgabe des Programmierers Datenbankänderungen, die nur einmal ausgeführt werden dürfen, zu erkennen und entsprechende Maßnahmen zu ergreifen. 12. Änderungen in der Session Objekte in REQUEST.SESSION müssen so geändert werden, daß Zope die Änderungen erkennt. Hierzu kann z.B. eine Kopie des Objekts angelegt werden, die dann verändert und komplett zurückgeschrieben wird.