Sektionen
Benutzerspezifische Werkzeuge
Sie sind hier: Startseite Support Dokumentation docs Zope - BrowserViews

Zope - BrowserViews

Die mit Zope3 eingeführten BrowserViews finden sich heute in vielen Zope Anwendungen wieder. Im folgenden wird der grundlegende Aufbau und die Registrierung Beispielhaft erläutert. Weiterhin wird das Überschreiben von __init__- und __call__-Methoden erklärt.

BrowserView-Registrierung

Eine BrowserView wird wie folgt in einer configure.zcml-Datei definiert.

<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="inqbus.viewtests">

<browser:page
for="*"
name="my_view"
class=".views.MyView"
template="./templates/my_view.pt"
permission="zope2.View"
/>

Es ist auch möglich das Template in der Klasse zu definieren und die Angabe hier weg zu lassen, da dies aber eher der Übersicht entgegen wirkt, wird hier nicht weiter darauf eingegangen.

BrowserView-Klasse

Im folgenden Code-Block sieht man eine Beispielklasse einer Zope3 BrowserView, in der sowohl die __init__- als auch die __call__-Methode überschrieben wurde.

from zope.publisher.browser import BrowserView

class MyView(BrowserView):
""" eine test view
"""

def __init__(self, context, request):
""" der contructor einer view muss nur selten überschrieben werden,
z.B. um wie hier einen Parameter aus dem
TraversalRequestNameStack zu extrahieren.
self.context und self.request werden immer im constructor
definiert, daher müssen wir dies hier auch tun.
"""
self.context = context
self.request = request
travers_name_stack = self.request.get('TraversalRequestNameStack')
if travers_name_stack:
self.my_param = travers_name_stack.pop()

def setup(self):
""" Diese setup Methode ermittelt das Portalobjekt,
die Id des aktuell angemeldeten Nutzers
und die aktuelle URL ohne Query-Parameter.
Diese werden alle als Attribute der View abgelegt
und sind so in allen Methoden und im Template der View verwendbar.
"""
self.portal = queryUtility(IPloneSiteRoot)
self.member_id = portal.portal_membership.getAuthenticatedMember().getId()
self.current_base_url = getMultiAdapter((self.context, self.request),
name=u'plone_context_state').current_base_url()

def __call__(self):
""" die __call__ methode wird automatisch beim Aufruf der View
ausgeführt und ist daher ein guter Startpunkt für die
Initialisierung einer View.
Hier wird als erstes self.setup() aufgerufen und am Ende
die mittels self.index() gerenderte View zurück gegeben.
"""
self.setup()
return self.index()

Eine BrowserView kann auch nur aus eigenen Methoden bestehen, die man dann aus dem Template mittels "view/meine_methode" oder in Ausnahmefällen per Python-Ausdruck "python: view.meine_methode('hallo')" ansprechen kann. Es sollte aber vermieden werden Python Code in Templates zu verwenden, da es weder schnell noch gut lesbar ist!

from Products.Five.browser import BrowserView

class MyView(BrowserView):
""" eine test view
"""

def personal(self):
""" Gibt eine liste von personen daten zurück in der folgenden
Form zurück: [
{'vorname': 'Maik', 'nachname': 'Derstappen'},
 {'vorname': 'Otto', 'nachname': 'Jaenisch'},
]
"""
personal_liste = [
{'vorname': 'Maik', 'nachname': 'Derstappen'},
{'vorname': 'Otto', 'nachname': 'Jaenisch'},
]
return personal_liste

Die Daten dieser Methode können wie folgt in einem Zope Page Template ausgegeben werden.

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="inqbus.viewtests">
<body>
<metal:main fill-slot="main">
<tal:main-macro metal:define-macro="main">

<h1>Personal Liste</h1>
<ul tal:repeat="person view/personal"
tal:condition="view/personal|nothing">
<li>
<span tal:content="person/vorname" /> -
<span tal:content="person/nachname" />
</li>
</ul>

</tal:main-macro>
</metal:main>
</body>
</html>

Wie man sieht, wird per tal:repeat über die Liste der Personen iteriert und jede Person wird dann einzeln mit all ihren Feldern ausgegeben.

Ausdrücke wie dieser hier sind zu vermeiden!

<ul tal:repeat="person python:view.personal().items()"
tal:condition="view/personal|nothing">
<li>
<span tal:content="person/vorname" /> -
<span tal:content="person/nachname" />
</li>
</ul>

Dies wäre nötig wenn die Personen in einem Dictionary statt einer Liste zurückgegeben würden. Wie wir im obigen Beispiel sehen konnten, geht es auch anders.

Auch die folgende Datenstruktur läßt sich gut ohne Python-Ausdruck in einem Template ausgeben.

def erweiterte_personen_daten(self):
personen = [
{
'vorname': 'Maik',
'nachname': 'Derstappen',
'adressen': [
{
'strasse': 'Herloßsohnstr. 12',
'plz': '04155',
'ort': 'Leipzig',
},
{
'strasse': 'Laaver Weg 2',
'plz': '19273',
'ort': 'Neuhaus',
}
]
},
]
return personen

Die Ausgabe erfolgt in etwas so.

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="inqbus.viewtests">
<body>
<metal:main fill-slot="main">
<tal:main-macro metal:define-macro="main">

<h1>Personal Liste</h1>
<ul tal:repeat="person view/erweiterte_personen_daten"
tal:condition="view/personal|nothing">
<li>
<span tal:content="person/vorname" /> -
<span tal:content="person/nachname" />
<ul tal:repeat="adresse person/adressen">
<span tal:content="adresse/strasse" />
<span tal:content="adresse/plz" />
<span tal:content="adresse/ort" />
</ul>
</li>
</ul>

</tal:main-macro>
</metal:main>
</body>
</html>