Personal tools
Contact Us 24/7 > 1 866.SIX FEET
Sections

Skip to content. | Skip to navigation

Home > Blog > Deploying Plone and Zine together with Deliverance using Repoze

Blog

Deploying Plone and Zine together with Deliverance using Repoze

written by Calvin Hendryx-Parker on Monday April 27, 2009
Comments | Filed under: , , , ,

Using the right tool for the right job

Six Feet Up loves Plone, but using Plone as a blogging tool has never been a strong point. Blogging isn't something that we felt that Plone did well out of the box. Much like most Plone products, you have to add in various third party products or create your own products if you want to get some of the really nice features that many of the typical blogging platforms like WordPress offer today like pingbacks. We had tried quite a few of these ways of stuffing blogging into Plone and ran into various issues of dependencies or incompatibilities along the way so we decided to go for a solution that wasn't in Plone.

Zine is a blogging platform written in Python and supports being deployed as a WSGI application, so it seemed like the perfect fit. Zine is basically a python clone of WordPress and has all the nice goodies and plugins that modern blogging platforms have come to enjoy. It is also relatively easy to theme and write plugins to extend its behavior.

We can also run Plone as a WSGI application by using the Repoze application repoze.zope2 instead of the standard Zope ZPublisher. The big benefit is that we can run multiple WSGI applications in a single process and utilize WSGI middleware like Deliverance to theme all of the applications as they are delivered. This type of setup can simplify deployment greatly and all works well with buildout, which we have a lot of knowledge about already.

Bringing together the pieces

Let's start by getting repoze.zope2, zine and deliverance added to our buildout. I added four additional parts to our existing buildout profile to get this process started.

[buildout]
...
parts = 
  ...
  repoze # this needs to be before the zope2 part or plone won't work
  ...
  deliverance # these have to go at the end or paster won't get all the right eggs listed
  zine-deps
  zine

I also added this to the [buildout] section to pin the version of the zopelib:

find-links =
    ...
    http://dist.repoze.org/zope2/latest/zopelib-2.10.7.0.tar.gz

...
versions=versions

[versions]
zopelib = 2.10.7.0

In these four new parts we will add in the new bits required to host the full WSGI stack for our deployment. Here are the parts we added:

[repoze]
recipe = zc.recipe.egg
eggs =
     PasteScript
     WSGIUtils
     repoze.zope2
     ${plone:eggs}
index = http://dist.repoze.org/plone/latest/simple

[deliverance]
recipe = infrae.subversion
as_eggs = true
urls =
    http://codespeak.net/svn/z3/deliverance/trunk deliverance

[zine-deps]
recipe = zc.recipe.egg
extra-paths = parts/zine/lib/zine
interpreter = python
eggs = Paste
       PasteScript
       PasteDeploy
       ${instance:eggs}
       ${repoze:eggs}
       ${deliverance:eggs}
       SQLAlchemy>=0.5.0
       Jinja2>=2.1.0
       Werkzeug>=0.4
       simplejson
       html5lib
       pytz
       Babel>=0.9.4
       lxml>=2.0
       Pygments>=0.9
       docutils==0.5
       zinebuildout>=0.4
       MySQL-python

[zine]
recipe = zc.recipe.cmmi
url = http://zine.pocoo.org/releases/Zine-0.1.2.tar.gz
extra_options = --python=python

With all of that added to your buildout profile you need to re-run buildout and it will download and install all the needed parts for you.

Configuring the paster WSGI stack

Before we can start up the new WSGI stack with paster, we will need to create a paster.ini for the WSGI stack and a rules.xml file for deliverance to use.

You can put both of these files in the root of your buildout. The paste.ini is using the zinebuildout egg to allow us to use Zine as an application in our paster stack. It is configured in the [app:zine] section. You will need to make an empty zine directory in your buildout that will contain the zine.ini once Zine has been configured through the web.

The paste.ini file configures two pipelines, one for each application. The blog pipeline has the deliverance filter applied to it so you get the Plone theme applied to the Zine blog.

paste.ini

[DEFAULT]
debug = True

[app:zine]
use = egg:zinebuildout
instance_folder = %(here)s/zine

[app:zope2]
paste.app_factory = repoze.obob.publisher:make_obob
repoze.obob.get_root = repoze.zope2.z2bob:get_root
repoze.obob.initializer = repoze.zope2.z2bob:initialize
repoze.obob.helper_factory = repoze.zope2.z2bob:Zope2ObobHelper
zope.conf = %(here)s/parts/instance/etc/zope.conf

[filter:errorlog]
use = egg:repoze.errorlog#errorlog
path = /__error_log__
keep = 20
ignore = paste.httpexceptions:HTTPUnauthorized
       paste.httpexceptions:HTTPNotFound
       paste.httpexceptions:HTTPFound

[pipeline:zope]
pipeline = egg:Paste#cgitb
           egg:Paste#httpexceptions
           egg:repoze.retry#retry
           egg:repoze.tm#tm
           egg:repoze.vhm#vhm_xheaders 
           errorlog
           zope2

[pipeline:blog]
pipeline = egg:Paste#cgitb
           egg:Paste#httpexceptions
           errorlog
           deliverance
           zine

[filter:deliverance]
use = egg:deliverance#main
rule_filename = %(here)s/rules.xml

[server:main]
use = egg:repoze.zope2#zserver
host = localhost
port = 51047

[composite:main]
use = egg:Paste#urlmap
/blog = blog
/zope = zope

Configuring Deliverance to theme Zine with the Plone site theme

Deliverance is configured in the rules.xml file and points to the Plone application's main_template to get the look and feel. The rest of the rules drop bits that aren't needed and throw the Zine portlets and content into the right places in the Plone theme. We created a Zine plugin to wrap the Zine portlets with a more Plone like structure so that they blend right into the Plone theme.

rules.xml

<ruleset>
<theme href="/zope/Plone/main_template" />
<rule>
  <prepend theme="//head" content="//head/link" nocontent="ignore" /> 
  <prepend theme="//head" content="//head/style" nocontent="ignore" />
  <append theme="//head" content="//head/script" nocontent="ignore" />    
  <append theme="//head" content="//head/meta" nocontent="ignore" />
  <replace theme="//head/title" content="//head/title"  nocontent="ignore" />
  <!-- we don't need the reddit zine links -->
  <drop content="//div[@class='reddit']"/>
  <!-- let's drop the breadcrumbs from the plone theme -->
  <drop theme="#portal-breadcrumbs"/>
  <!-- let's drop the plone login box -->
  <drop theme="//td[@id='portal-column-one']/div/div"/>
  <!-- put the zine portlets in column one -->
  <append theme="//td[@id='portal-column-one']/div" content="//div[@class='sidebar']/*" nocontent="ignore"/>
  <!-- put the body of the zine in the content region -->
  <append theme="children:#region-content" content="children://div[@class='contents']" nocontent="ignore" />
  <!-- put the administrative links in column two -->
  <prepend theme="children:#portal-column-two" content="//div[@class='body']/ul" nocontent="ignore"/>
  <!-- make sure the login box has a spot when we need it -->
  <append theme="#viewlet-above-content" content="//div[@class='login-box']" nocontent="ignore"/>
</rule>
</ruleset>

Time to start up paster

Once these are all in place and you have created the zine directory at the root of your buildout, we can start the paster server. It is started like this:

bin/paster serve paste.ini

Now in your browser you can go to http://localhost:8080/zope to see the Zope/Plone instance. You will need to add a Plone Site to your instance. In my demo I gave it an id of "Plone". If you have a Plone Site with a different id, you will need to change the path to the in your rules.xml.

Now, when you go to http://localhost:8080/blog you will be presented with the Zine setup screens. If all went well, the screens should look like your Plone Site theme. At this point you will need to setup a MySQL database to hold the blog data and provide connection information as you go through the Zine setup wizard.

Now you can fix up and modify the rules.xml and theme in your Plone site to make the Zine blog blend into your site seamlessly. Enjoy!

Download the buildout used in this post

 

 
Posted by on Apr 30, 2009 10:50 AM
This is excellent! My first reaction after downloading Zine and trying to install it's various dependencies was, "a buildout script would have been nice..". My friend Jace is adding some features and fixes (Wordpress imports etc) to Zine here: bitbucket.org/jace/zine-main/ . I'll try to extract the zine buildout bits from here and contribute to the project. Thanks for the detailed tutorial.
Posted by on Apr 30, 2009 04:39 PM
Can you post the buildout.cfg in its entirety? Thanks!
Posted by on Apr 30, 2009 11:42 PM
More specifically, I am trying to understand how to get your changes into a buildout.cfg produced from paster create -t plone3_buildout MyPlone. My attempts to edit my buildout.cfg look like: [buildout] parts = repoze zope2 productdistros instance zopepy deliverance zine-deps zine - Change the number here to change the version of Plone being used extends = dist.plone.org/release/3.2.1/versions.cfg versions = versions - Add additional egg download sources here. dist.plone.org contains archives - of Plone packages. find-links = dist.plone.org/release/3.2.1 download.zope.org/ppix/ download.zope.org/distribution/ effbot.org/downloads dist.repoze.org/zope2/latest/zopelib-2.10.7.0.tar.gz versions=versions [versions] zopelib = 2.10.7.0 - Add additional eggs here eggs = - Reference any eggs you are developing here, one per line - e.g.: develop = src/my.package develop = [zope2] - For more information on this step and configuration options see: - pypi.python.org/pypi/plone.recipe.zope2install recipe = plone.recipe.zope2install fake-zope-eggs = true additional-fake-eggs = ZODB3 url = ${versions:zope2-url} - Use this section to download additional old-style products. - List any number of URLs for product tarballs under URLs (separate - with whitespace, or break over several lines, with subsequent lines - indented). If any archives contain several products inside a top-level - directory, list the archive file name (i.e. the last part of the URL, - normally with a .tar.gz suffix or similar) under 'nested-packages'. - If any archives extract to a product directory with a version suffix, list - the archive name under 'version-suffix-packages'. [productdistros] - For more information on this step and configuration options see: - pypi.python.org/pypi/plone.recipe.distros recipe = plone.recipe.distros urls = nested-packages = version-suffix-packages = [instance] - For more information on this step and configuration options see: - pypi.python.org/pypi/plone.recipe.zope2instance recipe = plone.recipe.zope2instance zope2-location = ${zope2:location} user = admin:admin http-address = 8080 #debug-mode = on #verbose-security = on - If you want Zope to know about any additional eggs, list them here. - This should include any development eggs you listed in develop-eggs above, - e.g. eggs = Plone my.package eggs = Plone ${buildout:eggs} - If you want to register ZCML slugs for any packages, list them here. - e.g. zcml = my.package my.other.package zcml = products = ${buildout:directory}/products ${productdistros:location} [zopepy] - For more information on this step and configuration options see: - pypi.python.org/pypi/zc.recipe.egg recipe = zc.recipe.egg eggs = ${instance:eggs} interpreter = zopepy extra-paths = ${zope2:location}/lib/python scripts = zopepy [repoze] recipe = zc.recipe.egg eggs = PasteScript WSGIUtils repoze.zope2 ${plone:eggs} index = dist.repoze.org/plone/latest/simple [deliverance] recipe = infrae.subversion as_eggs = true urls = codespeak.net/svn/z3/deliverance/trunk deliverance [zine-deps] recipe = zc.recipe.egg extra-paths = parts/zine/lib/zine interpreter = python eggs = Paste PasteScript PasteDeploy ${instance:eggs} ${repoze:eggs} ${deliverance:eggs} SQLAlchemy>=0.5.0 Jinja2>=2.1.0 Werkzeug>=0.4 simplejson html5lib pytz Babel>=0.9.4 lxml>=2.0 Pygments>=0.9 docutils==0.5 zinebuildout>=0.4 MySQL-python [zine] recipe = zc.recipe.cmmi url = zine.pocoo.org/releases/Zine-0.1.2.tar.gz extra_options = --python=python --- Then I run python bootstrap, then bin\buildout -v. This is what I get: C:\PloneZineDeliverance>bin\buildout.exe -v Installing 'zc.buildout', 'setuptools'. We have the distribution that satisfies 'zc.buildout==1.1.1'. We have the distribution that satisfies 'setuptools==0.6c9'. While: Installing. Getting section repoze. Initializing section repoze. Getting option repoze:eggs. Getting section plone. Error: The referenced section, 'plone', was not defined. Any ideas?
Posted by on May 01, 2009 10:18 AM
This is a great help, ties things together for me. Looking forward to trying it out. Thanks.
Posted by on May 01, 2009 11:01 AM
Hey Rob, I attached a tarball to the post that has the complete buildout inside. Enjoy! Cal
Posted by on May 01, 2009 03:08 PM
The buildout file needs to include PIL, without which the plone products were not available for install in the ZMI.
Posted by on Jul 12, 2009 05:39 AM
Have you any experience on deploying multiple zine instances with one paste deploy? It seems that zine only works with one zine instance per python interpreter so you'd need paste to somehow fire it off in a separate python instance somehow. Any thoughts?
Posted by on Jul 12, 2009 01:05 PM
Good tutorial - very helpful! I made buildout quite similar to solution described in this blog post. It uses Plone 3.3rc4, deliverance 0.3 and mod_wsgi for production. In development it also includes useful addons (like: stxnext.pdb, or egg:Paste#evalerror). lichota.pl/blog/2009/07/12/buildout-for-plone-3-with-deliverance-on-wsgi
Add comment

You can add a comment by filling out the form below. Plain text formatting.

puzzle

Next Steps


Select a type of support:

Contact our sales team

First Name:  
Last Name:  
Email Address:  
Phone Number:
Message:  
Fight spam:
What is + ?  
 
Call Us 1 866.SIX FEET
Sections