Planet Plone

This is where developers and integrators write about Plone, and is your best source for news and developments from the community.

January 30, 2015

Jazkarta Blog: How to Create a Badge System in Plone

by davisagli at 2015-01-30T19:57:47Z

With thousands of volunteers taking and teaching courses, climbing peaks, and donating time and money for environmental advocacy and youth programs, The Mountaineers needed a way to recognize their members’ contributions and skill levels. To let them do this, we created a badge system for their Plone website:

Mountaineers Badges

Members who complete milestones like graduating from a course or summiting a set of peaks are awarded a badge, which shows on their profile page.

Mountaineers Profile Badges

This feature was easy to implement because of another Plone add-on, collective.workspace, which we had already created to provide roster functionality for The Mountaineers’ courses, activities, and committees, allowing each participant’s role, registration status, and other information to be managed. Here are instructions for how to create a badge system on your own Plone site with the help of collective.workspace. The screenshots are from a Plone 5 site but this will also work in Plone 4.

  1. Add collective.workspace to your buildout:
    eggs = collective.workspace
  2. Start Plone, go to the Add-ons control panel in Site Setup, and activate collective.workspace.

  3. Go to the Dexterity Types control panel and add a Badge content type.
  4. Add an image field to hold the badge image.
    Screen Shot 2015-01-30 at 10.42.39 AM
  5. Go to the Behaviors tab and enable the “Team workspace” behavior.
    Screen Shot 2015-01-30 at 10.44.21 AM
  6. Now add a Badge to the site.
    Screen Shot 2015-01-30 at 10.47.51 AM
  7. There’s now a Roster link on the toolbar when viewing the badge.
    Screen Shot 2015-01-30 at 10.48.47 AM
  8. On the roster, we can add a user, indicating that they have been granted the badge.
    Screen Shot 2015-01-30 at 10.52.57 AM
    (Position is more useful for a committee roster. Selecting the Admins group gives the user permission to help manage this roster.)
  9. Now the user shows up on the badge roster.
    Screen Shot 2015-01-30 at 10.53.29 AM
  10. This isn’t particularly useful unless we make the user’s badges show up somewhere. Customize the author template and add this TAL:
      <tal:b repeat="badge python:context.portal_catalog(portal_type='badge', workspace_members=username)">
        <img src="${badge/getURL}/@@images/image/thumb" class="image-left" title="${badge/Title}" />
      <br style="clear: both;" />
  11. Now the assigned badges show up on a user’s profile!
    Screen Shot 2015-01-30 at 11.12.03 AM

That’s it! Enjoy your new badge system!

Tagged: badge system, Customizing Plone, Plone Add-ons

January 29, 2015

Six Feet Up: How to allow users to create site content using PloneFormGen

by Christine Shaw at 2015-01-29T12:00:00Z

Plone content image


Let's pretend you've got a website featuring press releases about science and technology. You'd like to let your visitors submit their own press releases without having a site login. You're in luck! In this article, we'll cover two ways to achieve this task using PloneFormGen.

Site content can be created via PloneFormGen with a Custom Script Adapter or by using an add-on adapter called PloneFormGen Save Data to Content (uwosh.pfg.d2c). Additionally, you could write python scripts to handle the submissions, but we will not be covering that method.

Creating Content using a Custom Script Adapter

1. Add and publish a new Folder to the root of your site called "User Content." This is where the new content will be saved.

2. Add a FormFolder, titled "Press Releases" and uncheck "Mailer" for the Action Adapter. Save.

3. Delete the default fields (comment, etc.) and add two required fields:

  • String Field : Press Release Title
  • Text Field : Press Release Content

4. Add a new Custom Script Adapter to the FormFolder via the Add New menu:

  • Set the Proxy Role to "Manager" (note the security risk here -- make sure your form does what you think it does and nothing else!)
  • Create the script which will create the new content. For our example, we're creating a Page (Document) in the site:
# Target folder is the newly-created Press Release folder
from Products.CMFCore.utils import getToolByName
urltool = getToolByName(context, "portal_url")
portal  = urltool.getPortalObject()
targetdir = getattr(portal, 'user-content')

# The form being submitted so we can access its contents
form = request.form

# Create a unique ID
from DateTime import DateTime
uid = str(DateTime().millis())

# Create a new Page (Document)
targetdir.invokeFactory("Document", id=uid, title=form['press-release-title'])

# Set the reference for our new Page
doc = targetdir[uid]

# Set the values for the content of the Page; use the short names of each item in the form
# (which you can see in the URL if you are viewing one of the fields directly)

# Reindexed the Page in the site

The item will be in the Private state by default, so you can review what was submitted. If you wanted to submit it for publication so that the state is Pending Review, append the following to the script:

# Submit for Review
portal_workflow = getToolByName(context, 'portal_workflow')
portal_workflow.doActionFor(doc, 'submit')

Or if you want it to go straight to Published (risky!), simply replace 'submit' with 'publish'.

Creating Content using the Save Data Adapter

If you have the ability to install add-on products in your site, another method of creating content using PloneFormGen is to use the PloneFormGen Save Data to Content adapter (uwosh.pfg.d2c).

First, we'll need to set up the content type we want to create in the ZMI. Using the same example as above, let's say we want to create a Press Release in the site. This adapter requires the content type to have 'uwosh.pfg.d2c' configured as its 'product'. This can be achieved in one of three ways: adding it programmatically, with genericsetup profile, or copying the existing one in portal_types tool. We'll use the last method in this example.

To create the type:

1. In your site as admin, go to /portal_types/manage_main

2. Clone the content type FormSaveData2ContentEntry by using copy and paste.

3. Check the box next to your new copy and select Rename. For our example, rename it to "Press Release."


Rename 2

4. Click on the type's title (now "Press Release") to edit additional fields:

  • Change the Title to "Press Release".
  • Change the Description to something informative such as "A document used for Press Releases" (or you can delete the default text and leave it blank).
  • Since we'd like the Press Release to visually appear like a Document (Page) in the site, change the value for the following fields to document_view:
    • Initial view name
    • Default view method
    • Available view methods
  • If you would also like your type to be addable without the use of the PFG form (e.g., using the Add New menu by users with permission), check the box for Implicitly Addable.

Edit Type



To create the Form used by visitors to submit a Press Release:

1. Add a FormFolder, titled "Press Releases" and uncheck "Mailer" for the Action Adapter. Save.

2. Delete the default fields (comment, etc.) and add two required fields:

  • String Field: Press Release Title
  • Text Field: Press Release Content

3. Because the document_view template used to display the Press Release expects the body content to actually be referred to as the name "text," we need to change the short name of the Press Release Content field:

  • View the folder_contents of the form
  • Check the box next to "Press Release Content" and click "rename"
  • Change the "Short Name" to "text"

Rename 3

Rename 4

4. Add a new Save Data to Content Adapter to the FormFolder via the Add New menu:

  • Title: Create Press Release
  • Title Field: press-release-title
  • Saved Entry Content Type: Press Release

You can also choose which workflow to apply to a Press Release at this time.



5. Publish your form.

Anonymous visitors to the site may now submit Press Releases without needing an account to log in with on your site.

The Press Releases will be created inside the Content Adapter (it is folderish), and will be private by default unless you selected a workflow which allows the item to be automatically published. Because the Content Adapter is still private, these items will not be available via search. Publish and move approved items to a published folder location to have them searchable and visible to users on your site.

The layout view applied (document_view) will be the same as a Document (Page), so the title will appear in the title location and the body will display the content. If we were to just use the default base_view when creating the new Press Release content type, it would instead display the field names as captions to each item.

I hope this article helped give a basic understanding of how to allow your users to create site content with PloneFormGen. Have questions or comments? Sound off in the comments section below and be sure to sign up for our Plone & Python How-To digests to receive more how-to guides as soon as they are published!

eGenix: Python Meeting Düsseldorf - New Videos Online


The following text is in German, since we're announcing videos available from a regional user group meeting in Düsseldorf, Germany.

Was ist das Python Meeting Düsseldorf ?

Das Python Meeting Düsseldorf ist eine Veranstaltung, die alle drei Monate in Düsseldorf stattfindet und sich an Python Begeisterte aus der Region wendet.

Bei jedem Treffen werden Vorträge gehalten und anschließend in Diskussionen vertieft. Die Meetings dauern üblicherweise ca. 2 Stunden und münden anschließend in eine Restaurant-Session.

Teilnehmer kommen aus ganz Nordrhein-Westfalen, hauptsächlich allerdings aus der näheren Umgebung.

Neue Videos

Um die Vorträge auch für andere Python Enthusiasten zugänglich zu machen, nehmen wir die Vorträge auf, produzieren daraus Videos und laden diese auf unseren PyDDF YouTube Channel hoch.

In den letzten Tagen haben wir die Videos der letzten Treffen aufgearbeitet. Insgesamt sind 34 neue Videos dazugekommen. Viel Spaß damit:

Python Meeting Düsseldorf 2015-01-20

Python Meeting Düsseldorf 2014-09-30

Python Meeting Düsseldorf Sprint 2014 (2014-09-27/28)

Python Meeting Düsseldorf 2014-07-02

Python Meeting Düsseldorf 2014-04-29

Python Meeting Düsseldorf 2014-01-21

Python Meeting Düsseldorf 2013-11-19

Die vollständige Liste aller mehr als 70 Python Meeting Videos ist über unsere Video Liste verfügbar.

Weitere Informationen

Weitere Informationen und Termine rund um das Python Meeting Düsseldorf stehen auf unserer Webseite:


Viel Spaß !

Marc-Andre Lemburg,

January 28, 2015

Josh Johnson: Boot: Getting Started With Clojure In < 10 Minutes

by jjmojojjmojo at 2015-01-28T18:14:33Z

With the power of boot, it’s possible to go from “never used java before” to budding Clojure-ist cranking out jars like a pickle factory in record time. This post walks you through the process, and provides some post-‘hello world’ examples, with pointers to more information.


You will need the following: A JDK installed. Really, that’s it. Sun’s JDK or OpenJDK will work. Use the newest version.

You’ll need a way to download things. Feel free to use your browser. The examples below use wget.

If you’re on Linux or Mac OS, you’ll also need root access via sudo – this is not a hard requirement but allows you to install boot for everyone on your machine to use.

There’s an expectation that you know basic Clojure, and tries not to be too clever. For a good introduction, check out Clojure For The Brave and True, specifically Do Things: a Clojure Crash Course.
If you need help with specific forms used, the Clojure Community Documentation is extremely helpful, especially the Clojure Cheat Sheet.

It may be helpful to give the boot readme and wiki documentation a read. If you have questions about boot, IRC is a great way to get boot and clojure rockstars to help you out. Come join us on freenode, in #hoplon.

Dales la Bota (Give ‘em The Boot)

Boot is ‘installed‘ by simply downloading an executable file and putting it somewhere where you can execute it:

$ wget
$ mv boot && chmod a+x boot && sudo mv boot /usr/local/bin

The real magic happens when boot is run. Boot sets everything up in a .boot directory in your home folder. Without having any code to execute yet, you can trigger this by simply asking boot for help:

$ boot -h

Let’s Play With Clojure

Clojure utilizes a concept called a REPL (Read, Evaluate, Print, Loop). REPLs allow you to interactively run code and experiment.

$ boot repl

Boot then provides you with a prompt, where you can play around:

boot.user=> (+ 1 2 3 4 5)
boot.user=> (/ 10 0)
java.lang.ArithmeticException: Divide by zero

Boot also works as a scripting platform – you can construct applications, specifying dependencies, and parse command-line arguments.

Here’s a simple Clojure function that prints the fibonacci sequence to a given number of digits:

(defn fib
    (fib [0 1] n))
  ([pair, n]
    (print (first pair) " ")
    (if (> n 0)
      (fib [(second pair) (apply + pair)] (- n 1))

You can paste this into your REPL and try it out:

boot.user=> (defn fib
       #_=>   ([n]
       #_=>   (fib [0 1] n))
       #_=> ([pair, n]
       #_=>   (print (first pair) " ")
       #_=>   (if (> n 0)
       #_=>     (fib [(second pair) (apply + pair)] (- n 1))
       #_=>     (println))))
boot.user=> (fib 10)
0  1  1  2  3  5  8  13  21  34  55
We can transform that function into a command-line tool using the power of boot scripting. Assume this file is called fib.boot:
#!/usr/bin/env boot
(defn fib
    (fib [0 1] n))
  ([pair, n]
    (print (first pair) " ")
    (if (> n 0)
      (fib [(second pair) (apply + pair)] (- n 1))
(defn -main [& args]
  (let [limit (first args)]
    (println "Printing fibonacci sequence up to " limit "numbers")
    (fib (Integer/parseInt limit))))

Make the script executable:

$ chmod u+x fib.boot

Now you can run the script:

$ ./fib.boot 10
Printing fibonacci sequence up to  10 numbers
0  1  1  2  3  5  8  13  21  34

The script can declare dependencies, which will be downloaded as needed when the script is run.

Here, we’ll show the use of an external dependency: we can write a new fibonacci sequence that utilizes the fact that numbers in the sequence are related to each other by approximately the golden ratio (ca 1.62). Rounding makes it all work, but rounding isn’t “baked in” to Clojure, so we’ll use an external library to do it for us, called math.numeric-tower.

Ok, actually, it’s there, you just need to use some existing Java libraries to make it work – I admit this is a bit of a strain!

#!/usr/bin/env boot
(set-env! :dependencies '[[org.clojure/math.numeric-tower "0.0.4"]])
(require '[clojure.math.numeric-tower :refer [floor ceil round]])
(defn fib
  (loop [counter 0 x 0]
    (if (= counter 0)
      (do (print 0 " " 1 " " 1 " ")
        (recur 3 1))
    (let [y (round (* x 1.62))]
      (print y " ")
      (if (< counter 9)
        (recur (+ counter 1) y))))))
(defn -main [& args]
  (let [limit (first args)]
    (println "Printing fibonacci sequence up to" limit "numbers")
    (fib (Integer/parseInt limit))

When you run this code the first time, you’ll notice boot tells you that it’s downloaded some new jars:

$ ./fib.boot
Retrieving clojure-1.4.0.jar from
Retrieving math.numeric-tower-0.0.4.jar from
Printing fibonacci sequence up to  10 numbers
0  1  1  2  3  5  8  13  21  34

The syntax to define our -main function and parse our command line options can be a bit tedious. Luckily, we can borrow a macro from boot.core that lets us specify CLI options using a robust syntax.

For the full syntax, check out the documentation.

Here, we’ll let the user choose which implementation they’d like to use, and utilize the task DSL to do some simple command line options:

#!/usr/bin/env boot
(set-env! :dependencies '[[org.clojure/math.numeric-tower "0.0.4"]])
(require '[clojure.math.numeric-tower :refer [floor ceil round]])
(require '[boot.cli :as cli])
(defn fib
    (fib [0 1] n))
  ([pair, n]
     (print (first pair) " ")
     (if (> n 1)
       (fib [(second pair) (apply + pair)] (- n 1)))))
(defn fibgolden
  (loop [counter 0 x 0]
    (if (= counter 0)
      (do (print (str 0 "  " 1 "  " 1 "  "))
        (recur 3 1))
    (let [y (round (* x 1.62))]
      (print y " ")
      (if (< counter 9)
        (recur (+ counter 1) y))))))
(cli/defclifn -main
  "Print a fibonacci sequence to stdout using one of two algorithms."
  [g golden bool "Use the golden mean to calculate"
   n number NUMBER int "Quantity of numbers to generate. Defaults to 10"]
  (let [n (get :n *opts* 10)
        note (if golden "[golden]" "[recursive]")]
    (println note "Printing fibonacci sequence up to" n "numbers:")
    (if golden
      (fibgolden n)
      (fib n)))

Now you can see what options are available, tell the script what to do:

$ boot fib.boot -h
Print a fibonacci sequence to stdout using one of two algorithms.
  -h, --help           Print this help info.
  -g, --golden         Use the golden mean to calculate
  -n, --number NUMBER  Set quantity of numbers to generate. Defaults to 10 to NUMBER.
$ boot fib.boot
[recursive] Printing fibonacci sequence up to 10 numbers:
0  1  1  2  3  5  8  13  21  34
$ boot fib.boot -g -n 20
[recursive] Printing fibonacci sequence up to 20 numbers:
0  1  1  2  3  5  8  13  21  34  55  89  144  233  377  610  987  1597  2584  4181

Working At The Pickle Factory (Packing Java Jars and More Complex Projects)

Now that we’ve got a basic feel for Clojure and using boot, we can build a project, that creates a library with an entry point that we can use and distribute as a jar file.

This opens the doors to being able to deploy web applications, build libraries to share, and distribute standalone applications.

First, we need to create a project structure. This will help us keep things organized, and fit in with the way Clojure handles namespaces and files. We’ll put our source code in src, and create a new namespace, called fib.core:

$ mkdir -p src/fib

In src/fib/core.clj, we’ll declare our new namespace:

(ns fib.core
  (:require [clojure.math.numeric-tower :refer [floor ceil round]]
            [boot.cli :as cli])
(defn fib
    (fib [0 1] n))
  ([pair, n]
    (print (first pair) " ")
    (if (> n 1)
      (fib [(second pair) (apply + pair)] (- n 1)))))
(defn fibgolden
  (loop [counter 0 x 0]
    (if (= counter 0)
      (do (print (str 0 "  " 1 "  " 1 "  "))
          (recur 3 1))
    (let [y (round (* x 1.62))]
      (print y " ")
      (if (< counter 9)
        (recur (+ counter 1) y))))))
(cli/defclifn -main
  "Print a fibonacci sequence to stdout using one of two algorithms."
  [g golden bool "Use the golden mean to calculate"
   n number NUMBER int "Quantity of numbers to generate. Defaults to 10"]
  (let [n (if number number 10)
        note (if golden "[golden]" "[recursive]")]
    (println note "Printing fibonacci sequence up to" n "numbers:")
    (if golden
      (fibgolden n)
      (fib n)))

To build our jar, there are a handful of steps:

  1. Download our dependencies.
  2. Compile our clojure code ahead of time (aka AOT).
  3. Add a POM file describing our project and the version.
  4. Scan all of our dependencies and add them to the fileset to be put into the jar.
  5. Build the jar, specifying a module containing a -main function to run when the jar is invoked.

Helpfully, boot provides built-in functionality to do this for us. Each step is implemented as a boot task. Tasks act as a pipeline: the result of each can influence the next.

boot -d org.clojure/clojure:1.6.0 \
     -d boot/core:2.0.0-rc8 \
     -d org.clojure/math.numeric-tower:0.0.4 \
     -s src/ \
     aot -a \
     pom -p fib -v 1.0.0 \
     uber \
     jar -m fib.core

A brief explanation of each task and command line options:

Line 1-3: the -d option specifies a dependency. Here we list Clojure itself, boot.core, and math.numeric-tower.

Line 4: -s specifies a source directory to look into for .clj files.

Line 5: this is the AOT task, that compiles all of the .clj files for us. The -a flag tells the task to compile everything it finds.

Line 6: the POM task. This task adds project information to the jar. The -p option specifies the project name, -v is the version.

Line 7: the uber task collects the dependencies so they can be baked into the jar file. This makes the jar big (huge really), but it ends up being self-contained.

Line 8: finally, the jar task. This is the task that actually generates the jar file. The -m option specifies which module has the -main function.

Running the above command, produces output something like this:

$ boot -d org.clojure/clojure:1.6.0 \
>      -d boot/core:2.0.0-rc8 \
>      -d org.clojure/math.numeric-tower:0.0.4 \
>      -s src/ \
>      aot -a \
>      pom -p fib -v 1.0.0 \
>      uber \
>      jar -m fib.core
Compiling fib.core...
Writing pom.xml and
Adding uberjar entries...
Writing fib-1.0.0.jar...

At this point, there is a file named fib-1.0.0.jar in the target directory. We can use the java command to run it:

$ java -jar target/fib-1.0.0.jar
[recursive] Printing fibonacci sequence up to 10 numbers:
0  1  1  2  3  5  8  13  21  34

You can send this file to a friend, and they can use it too.

Introducing build.boot

At this point we have a project and can build a standalone jar file from it. This is great, but long command lines are prone to error. Boot provides a mechanism for defining your own tasks and setting the command line options in a single file, named build.boot.

Here’s a build.boot that configures boot in a manner equivalent to the command line switches above:

(set-env! :dependencies
          '[[org.clojure/math.numeric-tower "0.0.4"]
            [boot/core "2.0.0-rc8"]
            [org.clojure/clojure "1.6.0"]]
          :source-paths #{"src/"})
  pom {:project 'fib
       :version "1.0.0"}
  jar {:main 'fib.core}
  aot {:all true})

With build.boot in the current directory, you can now run the tasks like this:

$ boot aot pom uber jar
Compiling fib.core...
Writing pom.xml and
Adding uberjar entries...
Writing fib-1.0.0.jar...

The convenience of build.boot one step further, we can chain the tasks we want to use into our own task, using the deftask macro:

(set-env! :dependencies
          '[[org.clojure/math.numeric-tower "0.0.4"]
            [boot/core "2.0.0-rc8"]
            [org.clojure/clojure "1.6.0"]]
          :source-paths #{"src/"})
  pom {:project 'fib
       :version "1.0.0"}
  jar {:main 'fib.core}
  aot {:all true})
(deftask build
  "Create a standalone jar file that computes fibonacci sequences."
  (comp (aot) (pom) (uber) (jar)))

Now, we can just run boot build to make our standalone jar file. You’ll also see your task show up in the help output:

$ boot -h
   build                      Create a standalone jar file that computes fibonacci sequences.
$ boot build
Compiling fib.core...
Writing pom.xml and
Adding uberjar entries...
Writing fib-1.0.0.jar...

Where To Go From Here

At this point we’ve touched most of the awesomeness that boot gives us. With these basic tools, there’s all sorts of interesting things we can do next. Here are some ideas:

Benoît Suttor: Plone and Docker


In this post, I will try to explain how we put a new Plone site into production in our organization (IMIO, Belgium). For this process, we used some softwares as Puppet, Jenkins, but the process we use should be agnostic from these softwares.

January 26, 2015

Jazkarta Blog: Another Plone Site on AWS OpsWorks

by Sally Kleinfeldt at 2015-01-26T19:49:53Z

Congratulations to YES! Magazine on the launch of their redesigned website!

YES! Magazine

This award winning, ad-free, non-profit online (and print) magazine for progressive thinkers runs on Plone, our favorite CMS. Originally launched in 2009 by our friends at Web Collective and Groundwire (RIP), this is the first redesign the site has had since then. The focus was squarely on mobile usability (since 40% of site visits are now mobile) and social engagement. It looks great!

All the planning, analysis, and design work for the new site was done in-house; the Diazo theme implementation and site upgrade were done by Bryan Wilson, formerly of Web Collective. We helped a little bit as well: the YES! technical staff decided to host the new site on Amazon’s AWS cloud platform using the OpsWorks recipes for Plone and Python developed by Alec Mitchell. Alec walked Bryan through some of the technical details of the deployment stack and he was off and running.

We’re very pleased our Plone-OpsWorks contributions helped YES! Magazine!

Tagged: aws, deployment, OpsWorks, Plone, responsive design

January 25, 2015

JC Brand: Sprint Report: Merging Mockup and Patternslib


Alpine City Sprint, 21 to 26 January 2015

This is a report on what I did at the Plone Alpine City Sprint organized by Jens Klein and Christina Baumgartner in Innsbruck between 21 and 26 January 2015.

Firstly, I want to thank to them for organizing and hosting a great sprint and for being such friendly and generous hosts.

My goal for this sprint was to work on merging the Patternslib and Mockup Javascript frameworks and I'm happy to report that very good progress was made.

Long story short, the merge was successful and it's now possible to use patterns written for either project within a single framework.

Before I expand on how this was achieved during this sprint, I'll first provide some necessary background information to place things into context and to explain why this work was necessary.

What is Patternslib?

Patternslib brings webdesign and development together.

Patternslib's goal is to allow website designers to build rich interactive prototypes without having to write any Javascript. Instead the designer simply writes normal HTML and then adds dynamism and interactivity by adding special HTML classes and data-attributes to selected elements.

For example, here is a Pattern which injects a list of recent blog posts into a element in this page:

Click here to show recent blog posts

The declarative markup for this pattern looks as follows:

<section id="alpine-blog-injected">
    <a href="#portlet-recent-blogs"
       data-pat-inject="target: #alpine-blog-injected">
        Click here to show recent blog posts

The dynamic behavior comes from the fact that I have the Patternslib Javascript library loaded in this page.

On pageload, Patternslib scans the DOM looking for elements which declare any of the already registered patterns. If it finds such an element, it invokes a Javacript module associated with that pattern.

In the above example, the <a> element declares that it wants the Inject pattern applied to it, by virtue of it having the pat-inject HTML class.

Patterns are configured with specific HTML5 data properties. In the example above, it is the data-pat-inject property which specifies that the target for injection is the #alpine-blog-injected element in the current page and the content being injected is specified by the href attribute of the <a> element. In this case, the href points to an anchor inside the current page, but it might just as well be a link to another page which will then get injected via Ajax.

More information on how to configure pat-inject can be found on the patternslib website.

Each pattern has a corresponding Javascript module which is often just a wrapper around an existing Javascript library (such as Parsley, Select2 or Pickadate) that properly defines the configuration options for the pattern and properly invokes or applies the 3rd party library.

So, in order to do all this, Patternslib can be broken down into the folowing components:

  • A registry which lists all the available patterns.
  • A scanner which scans the DOM to identify declared patterns.
  • A parser which parses matched DOM elements for configuration settings.
  • The individual Javascript modules which implement the different patterns.

What is Mockup?

Mockup, declarative interaction patterns for Plone..

Mockup was inspired by, and originally based upon, Patternslib and was meant to bring the power of declarative interaction patterns to Plone.

When Mockup started, Patternslib was undergoing significant refactoring and development and it was decided that Mockup should fork and go its own way.

What this means is that the 4 different components mentioned above, were all changed and due to these changes the Mockup project diverged from Patternslib and started developing in a similar but different direction.

So what's the problem?

While Mockup was being developed for the upcoming Plone 5 release, we at Syslab continued using and improving Patternslib in our projects.

Syslab built an intranet for the Star Alliance, which was based on a prototype design by Cornelis Kolbach, the conceptual creator of Patternslib. This design became the inspiration and blueprint for the Plone Intranet Consortium (PIC), which consists of 12 companies working together in a consortium to build an intranet solution on top of Plone.

So, the PIC are building a product using Patternslib, while Plone 5 itself is being built with Mockup, an incompatible fork of Patternslib.

This was clearly a bad situation because we now had:

  • Two incompatible Javascript frameworks being used with Plone.

    Not only were the two frameworks incompatible in the sense that patterns written for the one don't work on the other, but they could also not be used on the same page since the two implementations would compete with one another in invoking Javascript to act upon the same DOM elements.

  • Duplication of effort

    The same or similar patterns were being developed for both frameworks, and when one framework had a pattern which the other wanted, it could only be used after being modified such that it couldn't be used in the original framework anymore.

  • A splitting of the available workforce.

    Developers were either working on Mockup or Patternslib, but almost never on both, which meant that the expertise and experience of developers wasn't being shared between the two projects.

How could this be fixed?

To solve the 3 main problems mentioned above, we needed to merge the common elements of Mockup (specifically the registry, scanner and parser) back into Patternslib.

This will allow developers from both projects to work on the same codebase and enable us to use patterns from both projects together.

At the Alpine City Sprint in Innsbruck, I worked on achieving these goals.

Changes brought in by Mockup

After the fork, Mockup introduced various changes and features which set it apart from Patternslib.

In order to merge Mockup back into Patternslib, I studied these changes and with the help of others came up with strategies on what needed to be done.

Here are some differences and what was done about them:

Mockup allows patterns to also be configured via JSON, whereas Patternslib used a keyword:argument; format

A week before the sprint I added JSON parsing ability to the Patternslib parser, thereby resolving this difference.

Leaves first parsing versus root first parsing

Mockup parses the DOM from the outside in ("root first"), while Patternslib parses the DOM from the inside out ("leaves first").

According to Rok Garbas, the creator of Mockup, the outside-in parsing was done because it reduced complexity in the scanner and the individual patterns.

Wichert Akkerman who originally wrote the Patternslib scanner however provided IMO a very good reason why he chose "leaves first" DOM scanning:

If I remember correctly there are several patterns that rely on any changes in child nodes to have already been made.This is true for several reasons: 1) a pattern may want to attach event handlers to child nodes, which will break of those child nodes are later replaced, and 2) child nodes changing size might impact any measurements made earlier.

Indeed, while refactoring the Mockup code during the merge, I ran into just such a case where a pattern couldn't yet be initialized because patterns inside it weren't yet initialized. By turning around the order of DOM scanning, this problem was resolved and the code in that pattern could be simplified.

So, now after the merge, scanning is "leaves-first" for Mockup patterns as well.

Mockup patterns are extended from a Base object, very similar to how Backbone does it

Patternslib patterns on the other hand are simple Javascript objects without constructors.

The patternslib patterns are conceptually very simple and more explicit.

However, what I like about the Mockup approach is that you have a separate instance with its own private closure for each DOM element for which it is invoked.

After merging, we now effectively have two different methods for writing patterns for Patternslib. The original "vanilla" way, and the Mockup way.

The Mockup parser was completely rewritten

The Mockup parser looks nothing like the Patternslib one and also supports one less configuration syntax (the so-called "shorthand" notation).

This was one piece of code which could not be merged within the time available at the Alpine City Sprint.

So currently we still have two different argument parsers. The Patternslib parser needs to be configured much more expicitly, while the Mockup one is more implicit and makes more assumptions.

Merging these two parsers will probably have to be done at some future sprint.

There are some other more minor differences, such as that every Mockup pattern is automatically registered as a jQuery plugin, but merging these was comparatively easier and I'll won't go into further detail on them.

What I did during the Alpine Sprint

So, in summary:

I refactored the Patternslib registry, scanner and some core utils to let them handle Mockup patterns as well. Luckily the eventual patch for this was quite small and readable.

I changed the Mockup Base pattern so that patterns derived from it now rely on the registry and scanner from Patternslib.

I fixed lots of tests and also wrote some new tests.

This whole task would have been much more difficult and error prone if either Patternslib or Mockup had fewer tests. The Mockup team deserves praise for taking testing very seriously and this allowed me to refactor and merge with much more confidence.

What else is there to still be done?

Being able to use patterns from both projects and merging most of the forked code was a big win, but there are still various things that need to be done to make the merge complete and viable.

I've ranked them from what I think is most important to least important.

1. Update the documentation

Currently documentation is scattered and silo'd in various places (the Patternslib website, the Plone Intranet developer docs and the Mockup developer docs).

The Mockup docs are now out of date ater this merge and need to be brought up to date on these recent changes.

The Patternslib docs are less of a problem because they don't have to deal with Mockup (which can now be seen as an enhancement suite for it), but they can definitely still be improved upon, specifically with an eye on Mockup developers who will start relying on them.

The Plone Intranet consortium also has a useful walkthrough explaining how to create a Patternslib pattern from scratch..

2. Devise a way to also use the Patternslib parser for Mockup patterns

As mentioned, the Mockup patterns still use their own argument parser.

Letting them use the Patternslib's parser will either require extending the Mockup Base pattern to configure the Patternslib parser on a pattern's behalf or instead doing it explicitly in each of the individual patterns.

3. Decide on coding and configuration standards

Unfortunately the coding standards between the two projects differ significantly.

  • The Mockup developers use camelCase as declarative argument names while Patternslib uses dash-separated names.
  • The Mockup source code uses 2 spaces for indentation, Patternslib uses 4 spaces.

4. Remove unnecessary, duplicated patterns

Both projects have patterns for modals, injection, select2 and file upload. These should be merged to get rid of duplication.

5. Move generic patterns (e.g. pat-pickadate, pat-moment etc.) out of Mockup

Mockup has some generic patterns which might also be useful as Patternslib core patterns, in which case they should ideally be moved there.


The sprint was a big success and I'm very happy that all the work has already been merged into the master branches of the matternslib, mockup and mockup-core repositories.

Core code from Mockup is now succesfully merged back into Patternslib and we can use patterns from both projects in the same site.

I had a lot of fun working with talented and motivated software developers and had a lot of opportunities to improve my German.

Thanks again Jens and Christine for organising a great sprint and I look forward to doing such a sprint again!

Innsbruck, the alpine city

January 23, 2015

Four Digits: Alpine City Sprint

by Kees Hink at 2015-01-23T16:25:00Z

Midden in de bergen van Tirol zijn de Plone-ontwikkelaars bezig de volgende release van Plone gereed te maken.

Er wordt mooie vooruitgang geboekt, zo wordt Plone's meertaligheid verbeterd, oude code wordt verwijderd, en het aantal submodules wordt verminderd. Al deze verbeteringen zullen in Plone 5 gereleased worden. Namens Four Digits is Kees hier aanwezig.

De sprint is woensdag begonnen, en loopt nog het hele weekend door.

Davide Moro: Kotti - avoid types addable in content root

by davide moro at 2015-01-23T13:16:49Z

With Kotti CMS ( you don't have to fight against the framework: after one or two days you'll love it and you will be productive.

You can add new content types mapped on database tables, extend existing ones, add one or more object actions, easy building of add and edit views without having to touch any html file.

Kotti is shipped with the pytest framework and I love it! The tests setup is very easy and you can mock or initialize your reusable fixtures with a dependency injection technique.

If your customer wants to use Windows, no problem:

How to prevent your content types to be added in content root

This blog post will explain how to prevent your content type to be added in the content root but only in Document types (they behave like folderish items too). What's the matter? The root itself is a Document.

My solution was similar to the following one, but a bit different:


from kotti.resources import TypeInfo
from kotti.resources import get_root
from kotti.resources import Content

class YourContentTypeInfo(TypeInfo):

    def addable(self, context, request):
        root = get_root()
        if context == root:
            return False
        return super(YourContentTypeInfo, self).addable(context, request)

yourcontent_type_info_data = Content.type_info.copy(
yourcontent_type_info = YourContentTypeInfo(**course_type_info_data)

class YourContent(Content):
    """ A yourcontent type. """


    id = Column(Integer, ForeignKey(''), primary_key=True)

    type_info = yourcontent_type_info
I tried to inherit all the default options and actions from the default Content's type info. This way you'll inherit all the backend menu actions.



After using Kotti for a while I can tell that the feedback is absolutely positive. It is the right choice when you don't need a much more complex system like Plone. So join the Python, Pyramid and Kotti community and say love to Kotti!

January 22, 2015

Andreas Jung: The case against Docker


Trying to use Docker for production for several week finally ended in the decision to let Docker for the moment.

January 19, 2015

Davide Moro: How to install Kotti CMS on Windows

by davide moro at 2015-01-19T10:14:17Z

Yes, as expected, you can install Kotti CMS also on Windows if you have this constraint!

What is Kotti

From the official doc:

"""A high-level, Pythonic web application framework based on Pyramid and SQLAlchemy. It includes an extensible Content Management System called the Kotti CMS.

Kotti is most useful when you are developing applications that:
  • have complex security requirements
  • use workflows, and/or
  • work with hierarchical data

It is developer friendly and with a good user interface. You can easily extend it, develop new features or install one of the available third party modules (search for Kotti on if you want to browse existing modules ready to be used). Heavily inspired by Plone (
If you want to evaluate Kotti you can install it locally (no database installation is required, you can use SQLlite during evaluation or development).
Otherwise if you are particular lazy there is a working demo online with admin / qwerty administrator credentials: 


  • python (tested with python 2.7.9 but it should work also on newer versions)
  • Microsoft Visual C++ 9.0 available on the following url (needed for an issue with bcrypt)
  • virtualenv (suggested)

Installation steps

Once you have installed python from you can start installing Kotti. I assume in this article that your Python installation path is C:\Python27.
Now create a new folder (it doesn't matter the name, in this article my folder name is just kotti):
> mkdir kotti
> cd kotti
Install virtualenv and create a new isolated python environment in your kotti dir:
> C:\Python27\Scripts\pip.exe install virtualenv> C:\Python27\Scripts\virtualenv.exe --no-site-packages .
Install Kotti and its requirements:
> Scripts\pip.exe install -r
> Scripts\pip.exe install Kotti

Put inside your kotti dir the app.ini file downloaded from:
Runs Kotti:
Scripts\pserve.exe app.ini
Starting server in PID 2452
serving on


If Microsoft Visual C++ Compiler for Python 2.7 is not installed on your environment you'll get an error during the requirements installation phase (only on Windows):
> Scripts\pip.exe install -r
  Running install for py-bcrypt
    building 'bcrypt._bcrypt' extension
    error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat).
Get it from
    Complete output from command C:\Users\dmoro\kotti\Scripts\python.exe -c "imp
ort setuptools, tokenize;__file__='c:\\users\\dmoro\\appdata\\local\\temp\\pip-b
uild-mact2r\\py-bcrypt\\';exec(compile(getattr(tokenize, 'open', open)(_
_file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record c:\u
sers\dmoro\appdata\local\temp\pip-wcmy6c-record\install-record.txt --single-vers
ion-externally-managed --compile --install-headers C:\Users\dmoro\kotti\include\
    running install

    running build

    running build_py

    creating build

    creating build\

    creating build\\bcrypt

    copying bcrypt\ -> build\\bcrypt

    running build_ext

    building 'bcrypt._bcrypt' extension

    error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat).
Get it from
You just need to install this requirement and all will work fine.



Kotti's front page (from the public demo online):

Kotti's folder contents (from the public demo online), requires authentication:

eGenix: eGenix Talks & Videos: Advanced Database Programming


eGenix Talk "Advanced Database Programming"

At last year's EuroPython 2014 conference in Berlin, Marc-André Lemburg, CEO of eGenix, gave the following talk on database programming in Python. We have now turned the talk into video presentation for easy viewing and also released the presentation slides:

EuroPython 2014 - Advanced Database Programming

Advanced concepts in Python database programming.

The Python DB-API 2.0 provides a direct interface to many popular database backends. It makes interaction with relational database very straight forward and allows tapping into the full set of features these databases provide.

This talk covers advanced database topics which are relevant in production environments such as locks, distributed transactions and transaction isolation. We also give advice on how to deal with common problems you face when working with complex database systems.

Click to proceed to the talk video and slides ...

Related Python Coaching and Consulting

If you are interested in learning more about these advanced techniques, eGenix now offers Python project coaching and consulting services to give your project teams advice on how to implement complex database architectures in Python. Please contact our eGenix Sales Team for information.

More interesting eGenix presentations are available in the presentations and talks section of the library on our website.

Enjoy !

Charlie Clark, Sales & Marketing

January 16, 2015

Davide Moro: Pyramid starter seed template powered by Yeoman (part 2)

by davide moro at 2015-01-16T10:58:10Z

In the previous blog post we have seen what are the
In the previous blog post we have seen what are the benefits of using the Yeoman workflow fully integrated with a web development framework like Pyramid. See:

Now we'll add more technical details about:
  • how to install pyramid_starter_seed and its prerequisites

How to install pyramid_starter_seed


    As you can imagine, nodejs tools are required.

    I strongly suggest to:
    • avoid system packages because they are too old
    • install nodejs with nvm (Node Version Manager)
    I won't cover the nodejs installation but it is quite simple if you follow these instructions provided by this useful link:
    The nvm achronym stands for NodeJS Version Manager. Once installed nvm, installing nodejs it is as simple as typing nvm install VERSION (at this time of writing 0.10.32).

    Nodejs is shipped with the command line utility named npm (Nodejs Package Manager) and we will use npm for installing what we need.

    We need to install our global (-g option) dev dependencies, so just type:
    $ npm install -g bower
    $ npm install -g grunt-cli
    $ npm install -g karma

    Starter seed project installation

    Create an isolated Python environment as explained in the official Pyramid documentation and instal Pyramid.

    Once installed you can clone pyramid_starter_seed from github:
    $ git clone
    $ cd pyramid_starter_seed
    $ YOUR_VIRTUALENV_PYTHON_PATH/bin/python develop
    Not finished yet, continue.

    Yeoman initialization

    Go to the folder where it lives our Yeoman project and initialize it.

    These are the standard commands (but, wait a moment, see the "Notes and known issues" subsection):
    $ cd pyramid_starter_seed/webapp
    $ bower install
    $ npm install --loglevel verbose
    Known issues:
    • if you are behind a proxy you'll have to configure properly npm
    • if you have a slow internet connection you might experience timeout problems.

    Build phase

    Just type:
    $ grunt
    and... probably it will fail because of a couple of known issues shipped with the latest version of generator-webapp or its dependencies.

    Probably these issues will be fixed in newer generator-webapp releases. However here it is how to solve these problems, so don't worry:
    1. grunt-contrib-imagemin fix
      Problem with grunt:
      Warning: Running "imagemin:dist" (imagemin) task
      Warning: Bad argument Use --force to continue.
      $ npm cache clean
      $ rm -fR node_modules       # not sure it is needed, don't remember
      $ npm install grunt-contrib-imagemin
    2. Mocha/PhantomJS issue
    Problem with Mocha/PhantomJS launching grunt
    Warning: PhantomJS timed out, possibly due to a missing Mocha run() call. Use --force to continue.
    $ cd test
    $ bower install
    Run bower install in the test directory of webapp (pyramid_starter_seed/webapp/test). This is a known issue, see

    Run you Pyramid app

    Now can choose to run Pyramid in development or production mode.
    Just type:
    $ YOUR_VIRTUALENV_PYTHON_PATH/bin/pserve development.ini
    $ YOUR_VIRTUALENV_PYTHON_PATH/bin/pserve production.ini

    In the next blog post with topic Pyramid + Yeoman (coming soon) I'm going to talk about:
    • how to manage things with grunt and personalize pyramid_starter_seed registering other assets
    • how to clone pyramid_starter_seed. Yes, you can easily customize it creating something of more sophisticated and create your own starter seed with another name. Without having to write a package generator
     So stay tuned..


Encolpe: Beats audio setup for HP Envy on recent Ubuntu

by encolpe at 2015-01-16T10:56:21Z

But the package hda-jack-retask is stuck in raring. The goal here is to allow you to install the package in your brand new Ubuntu. Replace « utopic » each time it is mentionned velow by your version.

sudo apt-add-repository -s ppa:diwic/hda
sudo apt-get update

Then edit  the file « /etc/apt/sources.list.d/diwic-ubuntu-hda-utopic.list » to replace utopic by saucy.

cd Downloads
mkdir hda-jack-retask
sudo apt-get build-dep hda-jack-retask
apt-get source hda-jack-retask
cd hda-jack-retask-0.20130613+raring

Now, you have to edit the debian/control file to sign the archive with you gpg key.
All spaces are important.

hda-jack-retask (0.20130613+utopic) utopic; urgency=low

* No-change upload for utopic

— Encolpe Degoute <> Fri, 16 Jan 2015 11:00:00 +0200

Now, prepare your local package ans install it :

dpkg-buildpackage -rfakeroot
sudo dpkg -i ../hda-jack-retask_0.20130613+utopic_amd64.deb

Remove the PPA:

sudo apt-add-repository -r ppa:diwic/hda

The overall process should take less than 10 minutes.

January 14, 2015

UW Oshkosh How-To's: How to embed video on a page

by ledwell at 2015-01-14T21:20:41Z

The problem

When you try and use TinyMCE and embed video code from Kaltura (or any video service) TinyMCE will strip out and rework the code such that the video will not display in Plone 4.3. When you go into "site setup > HTML Filtering" and adjust those setting TinyMCE continues to strip out the code. You can turn off TinyMCE and edit the code without the WYSIWYG editor then the code will not be modified on save and the video will display as expected. The problem with this solution is that someone else might come along who just wants to fix or change some text. If they were to use TinyMCE on that page with the functioning video then the code would be reworked on a save and the video which worked before would stop doing so.

You could try using;

David's option looks like it would work but you'd have to have more knowledge of monkeypatching and rights to access the file server, neither of which I have. 

For this to work you will need to have


Create a Snippet

  1. Activate "Snippets" (activating this product will create a folder called ".snippets" on the root level of your site
  2. Copy the embed code for the video you want to display
  3. Navigate to the root of your site and go into the /.snippets folder
  4. Choose "add new > page"
  5. Change "Text Format" to "textile" (this is mandatory! we do NOT want to use TinyMCE in anyway here).
  6. Paste your embed code
  7. IMPORTANT!. please title your file very simply. Do NOT use any goofy characters or spaces. The format should be, a-zA-Z0-9_ (if you name it incorrectly youll get an error when you try and insert the snippet. If that happens just go back and rename the snippet.)
  8. Save

Add your snippet to a page using TinyMCE

  1. Navigate to a page where you want your video (now a snippet) to appear
  2. Choose the "insert snippets icon" looks like this  {{}}
  3. Choose the "browse" button
  4. Choose your new Snippet 
  5. Choose the "Select" button
  6. If your happy with the preview choose the "insert" button

Positives Side Effects

This is a snippet that can be inserted in multiple places on your website. If you ever go to change the video for the snippet then all pages using that snippet get the new video as well.