Frage
Antwort
Für bestimmte Anwendungen muss man eine Liste von Objekten, die sich innerhalb eines Folder befinden, erstellen. Eine Anwendung ist zum Beispiel der Property Typ Selection, der einen Python Script als Argument erwartet, welcher eine List zurück gibt. Ein anderer Fall ist ein Page Template, welches zum Beispiel alle Bilder in einem Folder auflistet.
In diesen Beispielen wird von der Standardzuordnung ausgegangen:
##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters= ##title=
Einfachster Fall
Script gibt alle Objekte zurück, die sich in seinem Kontext befinden. Kontext ist der "Ort", von der der Script aufgerufen wird:
return [
ob
for ob in context.objectValues()
]
Script gibt die ID der Objekte zurück, die sich in dem selben Folder befinden, in dem auch der Script befindet, nur er selber wird nicht zurück gegeben:
return [
ob.getId()
for ob in container.objectValues()
if ob != script
]
Komplexere Beispiele
Script gibt ein Dictionary mit Id, Titel, Icon und Objekt im Kontext zurück, aber nur wenn es sich um ein DTML Dokumente, DTML Methoden oder Page Templates handelt und das Objekt nicht "index_html" heißt:
return [
{'id' : ob.getId(), 'title' : ob.title_or_id(), 'icon' : ob.icon, 'object' : ob}
for ob in context.objectValues(['DTML Document', 'DTML Method', 'Page Template'])
if ob.getId() != 'index_html'
]
(Hinweis: Effektiver wäre es, wenn man nur das Objekt zurück geben würde und Id, Icon und Titel an der Stelle erfragt, an der man diese Variable braucht. Das Beispiel hier zeigt nur die Möglichkeiten, die es gibt.)
Objekt nur dann in die Liste einfügen, wenn es ein bestimmtes Property besitzt:
return [
ob
for ob in context.objectValues()
if ob.hasProperty('PropertyName')
]
Nur dann eine Liste von Objekten zurück geben, wenn dieser Folder eine index_html besitzt:
if hasattr(container.aq_explicit, 'index_html'):
return [
ob
for ob in context.objectValues()
if ob.hasProperty('PropertyName')
]
else:
return []
(Hinweis: aq_explicit schaltet die Akquisition - vereinfacht gesagt - aus. Ansonsten würde Zope vielleicht in tieferen Ebenen nach einer index_html suchen. Wenn man sich nicht sicher ist, sollte man die Akquisition immer manuel mit den entsprechenden Methoden kontrollieren. "return []" kann man sich sparen, wenn man nicht zwingend eine Liste als Rückgabewert erwartet)
Königsbeispiel
Python Script:
##parameters=meta = ['Folder', 'Page Template', 'PropertyObject', 'PropertyFolder', 'Photo', 'PhotoFolder',]
# Falls meta leer ist (Script z.B: mit ("") aufgerufen), dann alle Objekte zurück geben
if meta:
objects = context.objectValues(meta)
else:
objects = context.objectValues()
# Erstelle eine Liste mit allen Objekten, die entweder kein Property "published" haben oder deren Property "published" True ist
ob = [ ob
for ob in objects
if not (hasattr(ob.aq_explicit, 'published') and not ob.published)
]
# Sortiere aufgesteigend (asc) und ohne Berücksichtigung der Groß/Kleinschreibung (nocase) nach Titel
# oder nach der Id, falls der Titel leer ist (title_or_id)
ob = sequence.sort(ob, (('title_or_id', 'nocase', 'asc'),))
# folder enthält alle Objekte, die sich wie ein Folder verhalten
# item enthält alle Objekte, die sich nicht wie ein Folder verhalten und nicht index_html heißen
return { 'folder' : filter(lambda x: x.isPrincipiaFolderish, ob),
'item' : filter(lambda x: not x.isPrincipiaFolderish and x.getId()!= 'index_html', ob),
}
Page Template (Ausschnitt):
<p tal:define="objects python: here.folderlist();">
<span tal:repeat="item objects/folder">
<img src="icon" tal:attributes="src item/icon" >
<a href="link" tal:content="item/title_or_id" tal:attributes="href item/id">link</a><br>
</span>
<span tal:repeat="item objects/item">
<img src="icon" tal:attributes="src item/icon">
<a href="link" tal:content="item/title_or_id" tal:attributes="href item/id">link</a><br>
</span>
</p>