Dieses Tuturial bietet Ihnen einen Überblick darüber, wie Sie verschiedene Aspekte von Plone 3 individuell anpassen. Es ist eine Übersetzung des englischen Originals von Martin Aspeli, Customization for developers von Plone.org. Einführung Was tun wir hier? Plone hat eine eine starke Kultur der individuellen Anpassung. Dies liegt daran, dass virtuell jeder Aspekt von Plone individuell angepaßt und überschrieben werden kann, ohne den originalen Quellcode anzufassen. Dieses Tuturial wird die Hauptwege behandeln, auf denen sichtbare Komponenten von Plone 3 von Entwicklern individuell angepaßt werden können.
Es ist für Seitenadministratoren möglich verschiedenste Vorlagen über das Web anzupassen, indem Sie entweder das Werkzeug portal_skins (für herkömmliche CMF-Oberflächenschichten-Ressourcen) oder das Werkzeug portal_view_customizations (für Zope-3-Ansichten, -Viewlets und -Portlets) benutzen. Wir werden die Unterschiede weiter unten im Text erklären, Die Anpassung über das Web passt ausgezeichnet für schnelle Lösungen oder für das Experimentieren, aber dies ist kein Weg, um ein seriöses Projekt zu erstellen oder zu entwickeln. Dieses Tuturial konzentriert sich auf dateibasierte Anpassungen, wie sie ein Entwickler in einem Ergänzungsprodukt von einem Drittanbieter vornehmen wird.
Dieses Tuturial demonstriert die Haupttypen der individuellen Anpassung unter Benutzung des Paketes mit dem Namen example.customization. Sie können es vom Cheese Shop herunterladen, in einer lokalen Python-Umgebung oder in einem Buildout installieren. Das buildout tutorial zeigt Ihnen, wie Sie ein ei-basiertes Produkt installieren. Vergessen Sie nicht einen ZCML-Slug zu installieren, falls Sie das Produkt austesten wollen. Falls einfach nur auf die letzte Version des Quellcodes schauen wollen, können Sie das Kollektive Subversion-Repository danach durchstöbern. Anpassung der Oberflächenschichten (Skin Layer) Der altmodische Weg Traditionell wurde die individuelle Anpassung in Zope mittels Akquise erledigt. Zum Beispiel kann ein Entwickler eine Seitenvorlage in die Wurzel (Root) der Seite platziert haben und die Vorlage dazu bekommen, ein Objekt im Unterordner /foo/bar zu rendern. Falls der Entwickler ein abweichendes Rendern nur für die Objekte in /foo/bar möchte, könnte er eine Vorlage mit demselben Namen (id) in diesem Verzeichnis platzieren, welche dann Vorrang erhält. Seit Plone (und das CMF) es überall für Seitenbenutzern zuläßt, ihre eigenen Hierarchien von Inhalten zu erstellen, wird das Platzieren von Vorlagen und Code innerhalb der Seitenstrukturen unschön. Deshalb erfanden die CMF-Entwickler das Werkzeug portal_skins. Falls Sie dieses Werkzeug im ZMI sehen, werden Sie eine oder mehr Skins (Oberflächen) auf seinem Register Properties finden, namentlich Plone Default. Eine Oberfläche (Skin) (welche wir neigen, als Themen zu bezeichnen, um Durcheinander zu vermeiden) ist lediglich eine geordnete Liste von Oberflächen-Schichten. Die Oberflächen-Schichten, die auf dem Register Properties (Eigenschaften) aufgelistet sind, korrespondieren mit den Verzeichnissen innerhalb des Werkzeugs portal_skins. Wenn Zope nach eine Ressource (sagen wir logo.jpg) schaut, wird es im aktuellen Verzeichnis suchen und danach in den Elternverzeichnissen aufwärts bis zur Seitenwurzel (site root). Falls die Ressource nicht gefunden werden kann, wird CMF nach ihr in den Oberflächen-Schichten für das aktuelle Thema schauen, beginnend oben auf der Liste und abwärts gehend, bis es das Passende findet. Beachten Sie, wie custom der erste Eintrag in der Liste ist. Dies ist wie die individuelle Anpassung über das Web arbeitet. Kopieren Sie ein Objekt in dieses Verzeichnis und die neue Kopie bekommt Priorität vor existierenden Eintragungen. Dies liegt daran, weil sie überhaupt nicht Verzeichnisse in der ZODB sind - sie sind Dateisystem-Verzeichnis-Ansichten (Filesystem Directory Views) - Verzeichnisse, die die Dateien innerhalb von bestimmten Verzeichnissen im Dateisystem wiedergeben. Um eine Produkt zu erstellen, das einige Ressourcen in einer Oberflächen-Schicht, die mit Plone geliefert wird, zu überschreiben, müssen wir deshalb: - Eine neue Dateiverzeichnis-Ansicht registrieren
- Diese in die Liste der Oberflächen-Schichten der aktuellen Oberfläche einfügen, normalerweise einfach unter dem Verzeichnis custom
- Kopieren der relevanten Ressource in das neue Oberflächen-Schichten-Verzeichnis, denselben Namen beibehaltend
- Diese Kopie individuell anpassen
Anmerkung: Einige der Ressourcen mögen eine zugeordnete Datei .metadata haben. Falls dies so ist, müssen Sie die Datei .metadata gemeinsam mit der Ressource kopieren, wenn Sie die Ressource individuell anpassen. Traditionell werden alle Plone-Ressourcen - Bilder, Stylesheets, Javaskript-Dateien, Seitenvorlagen und Python-Skripte wie Steuerprogramme für Formulare - in den Oberflächen-Schichten aufbewahrt. Allerdings wie Sie sich vorstellen können, wurde dies etwas mühsam, als Plone wuchs, da der Oberflächenmechanismus voraussetzt, dass jede Ressource einen allgemein einzigartigen Namen (id) hat. Noch immer werden die meisten der Hauptansichten, Bilder und Stylesheets, die Teil von Plone sind, in Oberflächen-Schichten (skin layer) aufbewahrt, die Namen mit einem Prefix plone_ haben, wie zum Beispiel plone_images oder plone_templates. Im Dateisystem finden Sie diese innerhalb von CMFPlone/skins. Sie können die Unterverzeichnissen dieses Verzeichnisses durchsuchen, um viele Ressourcen zu finden. Gewöhnlich, wenn eine Ressource in der Plone-Benutzerschnittstelle (Plone UI) aufgeführt ist (zum Beispiel über eine URL, eine Aktion (action) in portal_actions oder einen Alias in portal_types) und nicht mit einem Prefix entweder @@ (wie in @@view) oder ++resource++ (wie ++resource++stylesheet.css), dann kann sie voraussichtlich in einer Oberflächen-Schicht gefunden werden. Registrieren und Installieren einer neuen dateibasierten Oberflächen-Schicht (skin layer) In dem Produkt example.customization haben wir ein Unterverzeichnis skins/ mit einem einzelnen Oberflächen-Schichten-Verzeichnis, example_customiation. Damit wir in der Lage sind, dies als eine Dateisystem-Verzeichnis-Ansicht zu restrieren, müssen wir CMF über das Oberflächenverzeichnis der obersten Schicht informieren. Dies erledigen wir in der Datei __init__.py des Paketes: from Products.CMFCore.DirectoryView import registerDirectory
GLOBALS = globals() registerDirectory('skins', GLOBALS)
def initialize(context): """Intializer called when used as a Zope 2 product."""
Damit dies funktioniert, müssen wir sicherstellen, dass dieses Paket ein Zope-2-Produkt ist. Falls es in dem magischen Namensraum Products.* ist (zum Beispiel platziert sich ein traditionelles Produkt im Verzeichnis Products in einer Zope-Instanz), dann passiert das automatisch. Falls wir ei-basierte (egg-based) Produkte in einem abweichenden Namensraum benutzen, fügen wir der Datei configure.zcml des Paketes dies hinzu: <configure xmlns="http://namespaces.zope.org/zope" xmlns:genericsetup="http://namespaces.zope.org/genericsetup" xmlns:five="http://namespaces.zope.org/five" i18n_domain="example.customization">
<five:registerPackage package="." initialize=".initialize" />
...
</configure>
Wir müssen dann die Verzeichnisansicht erstellen und sie für die aktuelle Ansicht installieren, wenn das Produkt in einer Plone-Seite installiert wird. Dies erledigen wir durch das Benutzen von GenericSetup. Zuerst müssen wir ein neues Erweiterungsprofil (extension profile) registrieren, damit das Produkt installierbar ist. Dies geschieht folgendermaßen in der Datei configure.zcml: <genericsetup:registerProfile name="default" title="Example customizations" directory="profiles/default" description='Install various customizations from the example.customization package' provides="Products.GenericSetup.interfaces.EXTENSION" />
Dann benutzen wir das Importsteuerungsprogramm für skins.xml, um das Werkzeug portal_skins zu konfigurieren: <?xml version="1.0"?> <!-- This file holds the setup configuration for the portal_skins tool -->
<object name="portal_skins">
<object name="example_customization" meta_type="Filesystem Directory View" directory="example.customization:skins/example_customization"/>
<skin-path name="*"> <layer name="example_customization" insert-after="custom"/> </skin-path>
</object>
Falls wir wollen, können wir hier so viele Verzeichnisansichten, wie wir wollen, registrieren. Um alles zu testen, platzieren wir ein aufsehenerregendes neues Logo in skins/example_customizations/logo.jpg, welches logo.jpg von CMFPlone/skins/plone_images überschreibt. Wenn das Produkt installiert ist, werden Sie dieses Logo anstelle des Standard-Plone-Logo sehen. Eventuell müssen Sie für eine komplette Aktualisierung in Ihrem Browser sorgen. Browserschichten (Browser layers) Individuelle Anpassung: Zope-3-Stil Als Zope 3 konzipiert wurde, wurden viele der Aufgaben von CMF eingebaut und die Technologie verfeinert. Die Idee eines einzelnen globalen Namensraumes mit inidividueller Anpassung möglich nur über eine ID wurde verdrängt durch die Idee von benannten Ressourcen für einen Kontexttyp (so dass die Ansicht, wenn sie mit @@view auf eine Seite aufgerufen wird anders aussieht als derselbe Name aufgerufen auf ein Verzeichnis), und möglicherweise registriert für eine Browserschicht (Browser Layer). Ein Zope-3-Browserschicht ist ähnlich vom Zweck her wie eine CMF-Oberflächen-Schicht, aber sie wird anders verwirklicht. Eine Browserschicht ist nur ein Marker Interface, welches sich auf die Anfrage an die Traversale bezieht. Eine Zope-3-Browser-Ressource ist Mehrfach-Adapter für den Kontext und die Anfrage, und wenn die Anfrage mit einer bestimmten Schnittstelle gekennzeichnet ist, findet die Komponenten-Architektur eventuell einen spezifischeren Adapter in einer Ansicht (view), die für diese spezielle Schicht registriert ist. Falls dies nicht einleuten sollte, machen Sie sich keine Sorgen. Alles, was Sie wissen müssen, ist dies: - Wir definieren lediglich ein Marker Interface (welches lediglich ein Klasse ohne Inhalt ist, abgeleitet von zope.interface.Interface), der die Browserschicht abbildet.
- Wir stellen sicher, dass sich das Interface (die Schnittstelle) automatisch auf die Anfrage bezieht, indem wir die Browserschicht in unserer Seite aktivieren.
- Wir registrieren (unter Benutzen von ZCML) Browser-Ressourcen, Views (Ansichten), Viewlets und Portlets für diese neue Schicht, wobei wir ihnen erlauben, die Standardwerte zu überschreiben (welche ohne Bedingungen für die Standard-Browser-Schicht registriert sind).
In Plone gibt es zwei Hauptwege, um eine individuell angepaßte Browser-Schichten-Schnittstelle zu aktivieren. Der erste besteht darin, den Mechanismus von plone.theme zu benutzen. Dieses Paket, das mit Plone standardmäßig mitgeliefert wird, ermöglicht es uns, eine Browser-Schicht mit einem bestimmten Thema (Skin / Oberfläche) in portal_skins zu verbinden (um nicht zu verwirren mit einer Oberflächenschicht / skin layer). Wenn das Thema in portal_skins aktiviert ist, ist die Schicht gültig. Dies ist nützlich für Produkte, die ein ganz neues Thema in Plone installieren. Es ist weniger nützlich für allgemeine (nicht-themen) Produkte, da nur eine plone.theme-installierte Schicht zur gleichen Zeit aktiv ist. Wir wollen tatsächlich, dass die Schichteninstallation additiv (zusätzlich) ist, so dass wir jede Anzahl von Produkten installieren können, jedes seine eigene Schicht anbietend. Um dies zu tun, müssen wir das Paket plone.browserlayer benutzen. Dieses Paket ist nicht Teil von Plone 3.0 (aber seine Funktionalität wird Teil von Plone 3.1 sein). Wir müssen deshalb dieses Paket gemeinsam mit unserem Paket installieren. Da example.customization ein ei-basiertes (egg-based) Produkt ist, können wir plone.browserlayer einfach dadurch erhalten, dass wir es in setup.py voraussetzen. Dies erledigen wir mit einer Modifikation der Definition der install_requires (Installationsvoraussetzungen) in dieser Datei: install_requires=[ 'setuptools', 'plone.browserlayer', ],
Damit wird Buildout (oder easy_install) plone.browserlayer von PyPI herunterladen undd installieren. Wir müssen plone.browserlayer auch als Produkt installieren. Mangels einer Unterstützung für die Auflösung von Abhängigkeiten in GenericSetup (geplant für Plone 3.1), benutzen wir hierfür eine Datei Extensions/Install.py innerhalb unseres Produktes mit dem folgenden annähernden Standardcode: import transaction from Products.CMFCore.utils import getToolByName
PRODUCT_DEPENDENCIES = ('plone.browserlayer',) EXTENSION_PROFILES = ('example.customization:default',)
def install(self, reinstall=False): portal_quickinstaller = getToolByName(self, 'portal_quickinstaller') portal_setup = getToolByName(self, 'portal_setup')
for product in PRODUCT_DEPENDENCIES: if reinstall and portal_quickinstaller.isProductInstalled(product): portal_quickinstaller.reinstallProducts([product]) transaction.savepoint() elif not portal_quickinstaller.isProductInstalled(product): portal_quickinstaller.installProduct(product) transaction.savepoint() for extension_id in EXTENSION_PROFILES: portal_setup.runAllImportStepsFromProfile('profile-%s' % extension_id, purge_old=False) product_name = extension_id.split(':')[0] portal_quickinstaller.notifyInstalled(product_name) transaction.savepoint()
Hiermit wird plone.browserlayer ("Lokale Browserschichten-Unterstützung") installiert, wenn wir example.customiation installieren. Zope-3-Browser-Ressourcen Wie man Bilder und Stylesheets, die als Zope-3-Browser-Schichten registriert sind, individuell anpasst. Zope 3 erlaubt es Browser-Ressourcen, namentlich Bildern und Stylesheets, dass sie unter einem speziellen Namensraum registriert werden. Wenn Sie zum Beispiel eine Bild-Ressource mit dem Namen wibble.gif registrieren, wird die Browser-Ressource aufrufbar sein als http://yoursite.com/++resource++wibble.gif. Dies dient dazu, die Ressource aus dem flachen globalen Namensraum herauszubekommen. Browser-Ressourcen tun nicht viel selbst. Sie sind üblicherweise in einer Registry wie zum Beispiel portal_css, portal_javascripts oder portal_kss installiert oder benutzt in Aktionen (actions) oder anderen Verknüpfungen. Wie alle Zope-3-Browser-Komponenten sind Browser-Ressourcen registriert mit einer ZCML-Anweisung im Browser-Namensraum, die neben anderen Dingen ein Schichtenattribut (layer attribut) bringt.Die Schicht sollte zu einer Schnittstelle auflösen. Als Beispiel nehmen Sie das Paket plone.app.iterate. In seiner Datei browser/configure.zcml werden Sie die folgende Definition finden: <browser:resource name="checkout.png" image="checkout.png" />
Dies definiert eine Ressource, ++resource++checkout.png, die in der Aktion checkout genutzt wird, wenn iterate installiert ist. Falls wir dieses ziemlich hübsche Bild in ein ziemlich häßliches Pink verwandeln wollen, können wir es individuell anpassen für die Schicht IExampleCustomization. Mit einem individuell angepaßten Bild mit dem Namen ugly_checkout.png in unserem eigenen Verzeichnis browser/ werden wir das Folgende in browser/configure.zcml hinzufügen: <configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="example.customization">
...
<browser:resource name="checkout.png" image="ugly_checkout.png" layer=".interfaces.IExampleCustomization" />
...
</configure>
Beachten Sie, dass wir ohne das Attribut layer attribute einen Konfigurationskonflikt bekommen würden mit der originalen Definition von ++resource++checkout.png. Zope-3-Browser-Ansichten (Views) Individuelles Anpassen von Ansichten (Views) und Seiten Browser-Ansichten (Views) entsprechen etwa den Seitenvorlagen (page templates) (Dateien .pt) in Oberflächenschichten (skin layers). Allerdings sind sie im ZCML registeriert für einen bestimmten Inhaltstyp. Hier ist ein Beispiel aus plone.app.content.browser: <browser:page for="*" class=".reviewlist.FullReviewListView" name="full_review_list" template="full_review_list.pt" permission="cmf.ReviewPortalContent" />
Dies teilt uns mit, dass die Ansicht (view) aufgerufen wird über@@full_review_list (d @@ Eindeutigmacher ist nicht grundsätzlich notwendig, aber er macht klar, dass dies eine Ansicht [view] und nicht ein Inhalteelement ist). Es ist verfügbar für Benutzer, die zurzeit die Erlaubnis für Review portal content haben, und es ist verfügb ar für jeden Kontext (für="*"). Die Implementierung abgelegt in einer Klasse mit dem Namen FullReviewListView in reviewlist.py in dem aktuellen Verzeichnis, das unbedingt von einer Vorlage mit dem Namen full_review_list.pt gerendert wird. Ein Weg, um dies individuell anzupassen, besteht darin, eine Beeinflussung für einen spezielleren (oder abweichenden) Kontext vorzusehen. Das "*" ist der am meisten allgemeine Kontext (unter der Haube bedeutet dies zope.interface.interface). Falls wir unsere eigene Implementation für eine Standardseite haben (wie gekennzeichnet durch die Dokumentenschnittstelle Products.ATContentTypes.interface.document.IAT), können wir dies mit der folgenden Deklaration in der ZCML unseres eigenen Paketes erreichen: <browser:page for="Products.ATContentTypes.interface.document.IATDocument" class="plone.app.content.browser.reviewlist.FullReviewListView" name="full_review_list" template="document_full_review_list.pt" permission="cmf.ReviewPortalContent" />
Hier haben wir ausgewählt, die Standardschicht (default layer) zu benzutzen (Das bedeutet, wir haben keine Schicht spezifiziert), aber einen neuen Kontexttypen (das Attribut for, das auf die Schnittstelle für den in Frage kommenden Kontexttyp zeigt). Wir könnten eine neue Klasse (oder überhaupt keine) bereit gestellt haben, aber hier benutzen wir die Standard-Ansichts-Klasse von plone.app.content. Beachten Sie, dass wir es von einem relativen Modulpfad auf einen absoluten umgestellt haben, da wir nun in einem anderen Paket sind! Wir wechseln die Vorlage, die wieder relativ zum Verzeichnis ist, in dem sich die Datei ZCML befindet. Wir hätten wählen können, nur eine Klasse zu wählen oder nur eine Vorlage, falls dies mehr Sinn ergäbe. Alternativ können wir über Schichten individuell anpassen (und dies stellt sicher, dass die Anpassung nur dann Auswirkungen hat, wenn das Produkt installiert ist). Hier ist ein anderes Beispiel, dieses Mal die Standardansicht ersetzend durch eine neue bei Benutzen der alten Klasse mit einer neuen Vorlage. <browser:page for="*" class="plone.app.content.browser.reviewlist.FullReviewListView" name="full_review_list" template="standard_full_review_list.pt" layer=".interfaces.IExampleCustomization" permission="cmf.ReviewPortalContent" />
Beachten Sie, dass diese zwei Deklarationen koexisiteren können. In diesem Fall wird als Standard standard_full_review_list.pt benutzt, aber die Ansicht (view) auf eine Seite wird document_full_review_list.pt benutzen, da dies passender ist. Allerdings können wir beides tun - ein Überschreiben des Kontextes und eine Schicht benutzen. Das Resultat würde sein, dass das Überschreiben des Kontextes sich nur auswirkte, wenn die Schicht installiert ist. Ansichten (views) finden
Seitdem Ansichten (views) sich über Pakete ausbreiten, kann es manchmal sehr schwierig sein zu ermitteln, woher sie kommen. Oftmals ist das Durchführen einer Dateisuche in Ihrem Ei-Cache (egg cache) eine kurz und schmutzige (quick and dirty) Lösung. Allerdings können Sie stattdessen das Folgende tun: - Gehen Sie zu portal_view_customizations im ZMI, wo Sie die Ansichten (views), Viewlet und Portletrenderer finden werden, gruppiert zusammen durch ihre Kontenttypen. Schweben Sie Ihre Maus über den Ansichtentitel (view title) und Sie sollten einen Paketnamen und einen Vorlagennamen in einem Tooltip sehen.
- Hängen Sie /@@zptviews.html an das Ende einer bestimmten URL, zum Beispiel http://localhost:8080/plone/@@zptviews.html. Dies zeigt Ansichten (views) mit Vorlagen (aber nicht Viewlets oder Portletrenderer), zusammen mit Ihren Vorlagen, Kontexttypenschnittstelle und der Quell-ZCML-Datei.
Viewlets Individuelles Anpassen von Zope-3-Viewlets Viewlets sind Schnippsel einer Seite, geschrieben ein bißchen wie eine Ansicht (view), aber in die Seite gesetzt über einen Viewlet-Manager. Der Viewlet-Manager ist verantwortlich für das Finden, Ordnen, Filtern und Rendern seiner Viewlets. Die meisten Plone-Standard-Viewlets finden sich in dem Paket plone.app.layout. Hier ist ein Auszug aus seiner Datei viewlets/configure.zcml: <browser:viewlet name="plone.colophon" for="*" manager=".interfaces.IPortalFooter" template="colophon.pt" permission="zope.Public" />
Der Name ist eindeutig innerhalb des Portlet-Managers, der von einer Schnittstelle identifiziert wurde (und früher in derselben Datei unter Benutzen einer Anweisung <browser:viewletManager /> definiert wurde). Hier benutzen wir ein nur-vorlagen-basiertes Viewlet, definiert für jeden Kontext und nicht abgesichert durch irgendeine bestimmte Erlaubnis. Es ist möglich eine Klasse (class) stattdessen zu definieren oder der Vorlage hinzuzufügen. Wie Sie sicher schon geahnt haben, ist es möglich das Viewlet entweder über das Registrieren eines neuen Viewlets mit demselben Namen in demselben Manage, aber für einen spezielleren Kontext individuell anzupassen. Alternativ können wir ein neues Viewlet mit demselben Namen in demselben Manager registrieren, das eine angepaßte Schicht (layer) benutzt. Dies könnte aussehen wie dies: <browser:viewlet name="plone.colophon" for="*" manager="plone.app.layout.viewlets.interfaces.IPortalFooter" template="funny_colophon.pt" permission="zope.Public" layer=".interfaces.IExampleCustomization" />
Achten Sie darauf, wie wir den relativen Modulpfad zur Viewlet-Manager-Schnittstelle IPortalFooter in einen absoluten geändert haben und wie wir eine neue Vorlage bestimmt haben (errichtet relativ zu dem Verzeichnis, in dem unsere neu ZCML-Datei liegt). Schließlich ist es möglich, das Attribut view zu benutzen, um eine Schnittstelle oder eine Klasse einer Seitenansicht zu bestimme. MIt diesem Typ der individuellen Anpassung können Sie ein Viewlet haben, das auf verschiedenen Seiten unterschiedlich aussieht. Der häufigste Gebrauch hiervon in Plone besteht darin, Viewlets zu registrieren, die nur auf der Hauptansicht (main view) einer Seite angezeigt werden, indem die spezielle Marker-Schnittstelle IViewView benutzt wird, die für die aktuelle Ansicht während der Traversale gilt, falls der Benutzer auf dem Ansichten-Register des aktuellen Kontextes schaut. Hier ist ein Beispiel aus plone.app.layout.viewlets: <browser:viewlet name="plone.comments" for="Products.CMFCore.interfaces.IContentish" manager=".interfaces.IBelowContent" view="..globals.interfaces.IViewView" class=".comments.CommentsViewlet" permission="zope2.View" />
Wie für Ansichten (views) können Sie natürlich auch die Dimensionen für die individuelle Anpassung for, layer und view in Kombination benutzen. Viewlets finden
Das Werkzeug portal_view_customizations wird Ihnen die Viewlet-Registrierungen (und die Viewlet-Manager, für die sie registriert sind) zeigen. Wie bei Ansichten (views) können Sie über den Viewlet-Namen schweben, um in einem Tooltip zu sehen, wo es registriert ist. Um den Namen eines bestimmten Viewlets herauszufinden, können Sie die Ansicht (view) @@manage-viewlets benutzen, zum Beispiel wie in http://localhost:8080/plone/@@manage-viewlets. Für weitere Informationen über Viewlets sehen Sie sich an the tutorial on customising the viewlets in main_template (in englischer Sprache). Portlet-Renderer Plone-3-Portlet-Renderer individuell anpassen Portlets in Plone 3 sind nicht so unähnlich zu Viewlets, aber sie bestehen aus einer beständigen Komponente, dem Portlet Assignment, das die Konfiguration des Portlets enthält, welches wiederum unter Verwendung von einem Portlet Renderer gerendert wird. Für visuelle Anpassung wollen Sie an den Portlet-Renderer heran. Da Portlet-Renderer eine komplizierte Logik enthalten können und auf ein Paar bestimmten Registrierungstechniken beruhen, wartet Plone mit einer neuen ZCML-Anweisung - <plone:portletRenderer /> - auf, die die individuelle Anpassung des Portlet-Renderers ein wenig einfacher gestaltet. Im Unterschied zur individuellen Anpassung, die wir für die Standard-Browser-Ressourcen gesehen haben, wird eine nur-vorlagen-basierte individuelle Anpassung des Portlet-Renderers aktuell die Renderer-Ansicht-Klasse (wie seine Ansichten-/View-Variable), die benutzt wurde, um den Original-Portlet-Renderer zu registrieren. In plone.app.portlets unter portlets/configure.zcml werden Sie diese Definition für ein neues Portlet finden: <plone:portlet name="portlets.Recent" interface=".recent.IRecentPortlet" assignment=".recent.Assignment" renderer=".recent.Renderer" addview=".recent.AddForm" editview=".recent.EditForm" />
Sagen wir, wir wollten dies mit einer neuen Vorlage individuell anpassen. The default template (as referenced by the Renderer class in recent.py) is recent.pt in the same directory. Copying that to our own package, we can do the following: <configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" xmlns:plone="http://namespaces.plone.org/plone" i18n_domain="example.customization">
<!-- We need to include the package of the portlets we are customising --> <include package="plone.app.portlets" />
...
<plone:portletRenderer portlet="plone.app.portlets.portlets.recent.IRecentPortlet" layer=".interfaces.IExampleCustomization" template="mostly_recent.pt" />
</configure>
Beachten Sie, dass wir ausdrücklich das Paket plone.app.portlets in die ZCML-Ablaufsteuerung einbeziehen, da wir nun unbedingt seine Portet-Renderer-Klasse benutzen. Wir definieren dann einen neuen Portlet-Renderer mit einer individuell angepaßten Vorlage für unsere neue Schicht (layer). Es ist auch möglich, das Attribut for zu benutzen, um einen bestimmten Kontexttyp individuell anzupassen oder das Attribut view um eine bestimmte Ansicht (view) anzupassen, wie mit Viewlets. Anstatt eine individuell angepaßte Vorlage zu benutzen, können wir eine ganz neue Renderer-Klasse benutzen. Sehen Sie sich die Implementation in plone.app.portlets an, um zu verstehen, wie es funktioniert. Beachten Sie, dass im Unterschied zu Ansichten (views) und Viewlets Portlet-Renderer unterstützt entweder Vorlage (template) oder Klasse (class), aber nicht beides.
|