Tech-Blog
Technische Artikel zu Themen: Zope, Plone, Python, Pyramid, Django, Exim, Dovecot, Nagios, Shinken, Bacula und weiteren Open Source Themen...
Bibliotheken zur Konvertierung und Volltextindizierung von Dokumenten
Unter Debian Linux sind folgende Bibliotheken zu installieren
- poppler-utils
- libxslt1-dev
- libxml2-dev
- wv
- xsltproc
- unzip
Plone: den Owner (Besitzer) eines Objektes in Python ändern
Den Owner eines Objektes ändern
portal.plone_utils.changeOwnershipOf(obj, user_id) print "change owner of %s to %s" % (obj.id, user_id)
AngularJS: In einem controller einer directive mit isolated scope auf Methoden im parent scope zugreifen
Um in einer directive auf Methoden und Variablen zuzugreifen, kann man für diese ein Mapping erstellen: http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/
Will man aber in einem der directive zugewiesenen controller auf Methoden im parent scope zugreifen, kann man dies wie folgt machen.
Im controller der directive mappen wir unsere parent-Methode wie folgt:
$scope.toggleSomeThing = $scope.$parent.toggleSomeThing;
Nun können wir im Template der directive darauf zugreifen:
<button ng-click="toggleSomeThing(element)"></button
Quick Dexterity 2-Column-Edit-Form with Diazo
In the following we will separate the odd from the even fields into two div container.
Diazo rules and inline-XSLT to separate even from odd fields
In the main rules.xml file, we define a conditional include of our content type rules file my-contenttype.xml:
<rules css:if-content=".template-edit.portaltype-my-contenttype"> <xi:include href="my-contenttype.xml" /> </rules>
Then we define our rules to do the real work:
<?xml version="1.0" encoding="UTF-8"?> <rules xmlns="http://namespaces.plone.org/diazo" xmlns:css="http://namespaces.plone.org/diazo/css" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <replace css:content="#content-core fieldset"> <xsl:for-each select="."> <fieldset> <xsl:copy-of select="@*" /> <xsl:copy-of css:select="> legend" /> <div class="left-content-column"> <xsl:for-each css:select="> div.field:nth-child(even)"> <xsl:copy-of select="." /> </xsl:for-each> </div> <div class="right-content-column"> <xsl:for-each css:select="> div.field:nth-child(odd)"> <xsl:copy-of select="." /> </xsl:for-each> </div> </fieldset> </xsl:for-each> </replace> </rules>
CSS to show the two div container in two columns
body.template-edit.portaltype-my-contenttype{ .left-content-column{ width: 50%; float:left; .field{ padding: 0.5em; &:nth-child(even){ background: lightgray; } } } .right-content-column{ width: 50%; float:left; .field{ padding: 0.5em; &:nth-child(even){ background: lightgray; } } } }
New Markup Editor for Plone
If we edit HTML we get a fallback to TinyMCE editor. So we can just set MarkItUp as default editor and edit everythink we want with the proper editor.
MarkItUp Editor with reStructured Text and preview on bottom

By now Markdown and ReStructuredText works fine. And it has nice integration Plone to put in images and links like in TinyMCE.
collective.markitup does not provide any additional markup languages. It is just a editor you can use to edit Markdown, ReStructuredText or possibly any other markup you can choose in Plone's Markup settings control panel. By now Markdown (text/x-web-markdown) and ReStructuredText (text/restructured) works fine. And it has nice integration Plone to put in images and links like in TinyMCE.
MarkItUp Editor with finder integration, to choose images from Plone.

The new release of collective.markitup is out now: https://pypi.python.org/pypi/collective.markitup
Manage nodejs, grunt and bower with buildout
Buildout config
We can use gp.recipe.node recipe, for details see: https://pypi.python.org/pypi/gp.recipe.node
[buildout] parts += nodejs bower node_modules [nodejs] recipe = gp.recipe.node version = 0.10.22 npms = grunt-cli bower less jshint csslint blueimp-tmpl uglify-js scripts = grunt bower lessc jshint csslint tmpl.js uglifyjs [bower] recipe = collective.recipe.cmd shell = /bin/bash on_install = true on_update = true cmds = ./bin/bower install --config.interactive=false; echo $'\nBower modules installed.\n' [node_modules] recipe = collective.recipe.cmd shell = /bin/bash on_install = true on_update = true cmds = NODE_PATH="" bin/npm install .; echo $'\nNodeJS modules installed.\n'
Plone: Mit Diazo eine HTML-Liste in eine Selection verwandeln
Ausgangsstruktur
Das HTML des Portlets, welches nur die Unterordner anzeigt, also aus einer Ebene besteht, sieht wie folgt aus:
<dl class="portlet portletNavigationTree"> <dt class="portletHeader"> <span class="portletTopLeft"></span> <a href="http://127.0.0.1:8081/Plone/sitemap" class="tile">SubNavi</a> <span class="portletTopRight"></span> </dt> <dd class="portletItem lastItem"> <ul class="navTree navTreeLevel0"> <li class="navTreeItem visualNoMarker navTreeFolderish section-etwas-ueber-plone"> <a title="" class="state-published navTreeFolderish contenttype-folder" href="etwas-ueber-plone"> <span>Etwas über Plone</span> </a> </li> <li class="navTreeItem visualNoMarker navTreeFolderish section-etwas-ueber-python"> <a title="" class="state-published navTreeFolderish contenttype-folder" href="etwas-ueber-python"> <span>Etwas über Python</span> </a> </li> <li class="navTreeItem visualNoMarker navTreeFolderish section-etwas-ueber-zope"> <a title="" class="state-published navTreeFolderish contenttype-folder" href="etwas-ueber-zope"> <span>Etwas über Zope</span> </a> </li> </ul> <span class="portletBottomLeft"></span> <span class="portletBottomRight"></span> </dd> </dl>
Zielstruktur
Die HTML-Zielstruktur sieht wie folgt aus:
<div id="subNavWrapper"> <form action="" method="get"> <select name="subNavSel" size="1"> <option value="etwas-ueber-plone"Etwas über Plone</option> <option value="etwas-ueber-python">Etwas über Python</option> <option value="etwas-ueber-zope">Etwas über Zope</option> </select> </form> </div>
Diazo-Rules
Diazo-Rules (Regeln) zum umwandeln in die Zielstruktur:
<replace content-children="//dl[contains(@class, 'portletNavigationTree') and ./dt/a/text() = 'SubNavi']"> <select name="subNavSel" size="1"> <xsl:for-each select=".//ul[contains(@class, 'navTree')]/li/a"> <option><xsl:attribute name="value"><xsl:value-of select="./@href" /></xsl:attribute><xsl:copy-of select="./span/text()" /></option> </xsl:for-each> </select> </replace>
Plone: ContentType mit NamedBlobFile in tests erzeugen
Wir benötigen dazu eine Datei z.B. eine PDF-Datei, die wir programmatisch in unseren ContentType einsetzen können. Diese legen wir einfach in unserem tests-Verzeichniss, parallel zu unserem test ab.
Der folgende Code liest die Datei file.pdf ein und fügt sie in das Feld file des Objektes MyContentTypeObj
def getTestFile(filename): """ return contents of the file with the given name """ filename = os.path.join(os.path.dirname(__file__), filename) return open(filename, 'r') self.portal.invokeFactory( "MyContentType", id="mycontenttypeobj", title="My Content Type Obj", ) MyContentTypeObj = self.portal.get('mycontenttypeobj') data = getTestFile('file.pdf').read() MyContentTypeObj.file = NamedBlobFile( data=data, contentType='', filename=u'file.pdf')
Plone: Javascript Links in Texten erlauben
Das filtern von Javascript deaktivieren
Dazu müssen wir unter die Motorhaube, ins ZMI in /portal_transforms/safe_html gehen. Dort können wir den Wert für remove_javascript von 1 auf 0 ändern.
Danach am besten Plone neu starten, damit die Änderung wirklich sichtbar wird.
Plone: Kontakt-Link (site-action) für 2 Sprachen konfigurieren
Wir legen uns mit PloneFormGen ein Kontaktformular an und übersetzen dies, so dass wir nun 2 Formulare mit unterschiedlichem Namen (kontakt und contact) haben.
site-action URL Expression
Die folgende URL-Expression tragen wir in die entsprechende site-action in portal_actions ein.
python: plone_portal_state.language() == 'de' and globals_view.navigationRootUrl() + '/kontakt' or globals_view.navigationRootUrl() + '/contact'
Wenn es mehr als 2 Sprachen werden sollten, empfiehlt es sich hier ein ScriptPython zu verwenden welches den entsprechenden String dann zurück gibt.