Hello mod_wsgi

It seems I’ve inadvertently started another series of blog entry:  the “hello world” series, wherein I explain how to easily get started with various exciting Python technologies.

This time, in order to familiarize myself with mod_wsgi, I’ve created a buildout to automate some of the processes explained in:

(This series also helps me to subtly introduce the zc.buildout “extendables” I have been working on. More on those in a future post.)

The extendables

The extendables make it easy to bootstrap a development environment with complex software requirements, via zc.buildout. In this case, I want to be able to type:

$ test-apache test-dir

And get a working, disposable Apache instance minutes later. I also want that Apache to come with a mod_wsgi app installed and working.

Setup

First we use the aforementioned extendable, like so:

$ virtualenv test-dir
$ cd test-dir
$ bin/pip install zc.buildout
$ bin/buildout init

Edit the buildout.cfg to look like this:

[buildout]
extends = http://x.aclark.net/apache/2.2.x/buildout.cfg

Run buildout:

$ bin/buildout

Assuming successful completion, you should be able to run Apache in the foreground via:

$ bin/supervisord -e debug -n

Now check http://localhost:8080, you should see:

This works because the “extendable” (buildout configuration file) contains:

I like to automate the process even further with the following script:

#!/bin/sh

mkdir $1
virtualenv-2.6 $1
cd $1
bin/easy_install zc.buildout
bin/buildout init
cat << EOF > buildout.cfg
[buildout]
extends = http://x.aclark.net/apache/2.2.x/buildout.cfg
EOF
bin/buildout
bin/supervisord -e debug -n

Thus closing the loop on this blog entry, and making the following possible:

$ test-apache test-dir

I’ve been using my test-plone script for years now, and I’m hoping that the test-apache script proves just as useful (especially as Plone moves closer to a WSGI-supporting stack via Zope 2.13).

Hello Plone

This is a “hello world” style tutorial/application for Plone, aimed squarely at Python developers. I have created a project on Github too, to hold the code:

Step 1 – Setup

Everyone in the Python world loves virtualenv, so this step will be a familiar one. Inside the hello_plone repo, I first create a virtualenv:

$ virtualenv .

I then install some additional tools:

$ bin/pip install zc.buildout

As you see, Plone uses Buildout. One day it may not, but for now it does. Get over it. ;-) (Or better yet, help us figure out how to make Buildout optional in Plone. Many would welcome the improvement, and hail you as their conquering hero!)

Until then:

$ bin/buildout init

Edit your buildout.cfg and put this in it:

[buildout]
extends = http://build.pythonpackages.com/buildout/plone/4.2.x-dev

That’s it. Now run buildout:

$ bin/buildout

It will take some time to download all the packages, but you only have to do this once. Afterward, you can configure a global packages directory and share that amongst all your development projects. See the zc.buildout 1.5.2 page on PyPI to find out more.

When it finishes, do this:

$ bin/plone fg

Then open http://localhost:8080 and you should see this:

Click the button and follow the steps. You don’t need to select any additional add-ons from the list. Afterward, you should get a Plone site here: http://localhost:8080/Plone.

Step 2 – Develop

There are a ton of things you can do in Plone, but it is primarily a “content management system” meaning, “you put your website in it.”¹ And I don’t mean your “crazy cool next gen web app” website. I mean your web. site. The one you use for you or your business or church or band or bridge club or whatever.

Since this is a “hello world” demonstration, I am going to show you how to start writing Python code whose results will “show up on the screen” in short order. After that, I’ll point you to some next steps.

So, to develop we need a Python package. Create your own, or use zopeskel (paster wrapped in some “user friendliness”). Or use paster with the zopeskel templates installed.

$ bin/pip install zopeskel
$ bin/zopeskel plone_basic my.app

plone: A project for Plone add-ons

…

Now that we have a Python package, we want to “load it in Plone”. To do that, we need to add the package to our buildout. Fortunately, buildout has a mechanism for this particular use case built in. It’s called a “develop egg”, and it is configured via the `develop` parameter available in the `buildout` section.

Additionally, we need to “tell Plone” about our develop egg too. But this is done in the same way you tell Plone about any other package. You add it to the `eggs` parameter of the `plone.recipe.zope2instance` section.

So now we have:

[buildout]
develop = ./my.app
extends = http://build.pythonpackages.com/buildout/plone/4.2.x-dev

[plone]
eggs += my.app

Now let’s write some code. We are going to: “wire up a template to a view”, say “hello world!” then “call it a day”.

This is accomplished via some “goo” maintained by the Zope Toolkit project:

from Products.Five.browser.pagetemplatefile import \
    ViewPageTemplateFile
from zope.publisher.browser import BrowserPage

class Hello(BrowserPage):
    """
    Wire up some goo
    """

    template = ViewPageTemplateFile('hello.pt')

    def __call__(self):
        return self.template()

And it can go in: my.app/my/app/hello.py.

Now, because Plone uses the Zope component architecture, we need to “wire up” the “component” we just created. This is done via the Zope Configuration Markup Language:

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

    <browser:page

        for="*"
        name="hello"
        permission="zope2.View"
        />

</configure>

And it goes in: my.app/my/app/configure.zcml. It “just works” because we include an entry point in our setup.py to make it so (paster took care of that, in this case.)

Lastly, create: my.app/my/app/hello.pt.

And put “Hello world!” in it. Stop and start Plone (i.e. CTRL-C, bin/plone fg) and then open: http://localhost:8080/Plone/hello. You should see:

Nice, but a little boring. At the very least, let us get our “hello world!” to show up “in Plone”. To do this, we simply invoke Plone’s main_template and insert our text into the main content area.

Add the following to my.app/my/app/hello.pt.

<div metal:use-macro="here/main_template/macros/master">

    <div metal:fill-slot="main">

        <h1>Hello world!</h1>

    </div>

</div>

As you can see, we are using Zope Page Templates. ZPTs must be valid XHTML, much to the chagrin of Django’s creators. But in addition to the main con: “making humans edit XML is sadistic!”) there are some pros too e.g. “Play nicely with editing tools.” In other words, get over it. ;-) (Or better yet, add support for using alternative template languages in Plone. I have no idea what the technical feasibility is, but it might be worth some effort.)

Now let’s take a look:

Step 3 – Fun/profit!

That’s not so bad you say? (That is what I am hoping you will say!) Great. Some good next steps are:

Also, check out the Plone community managed developer documentation on readthedocs.org for more!

 

¹ c.f. SNL skit w/Rob Schnieder and/or Adam Sander too, apparently: http://www.youtube.com/watch?v=muA5EBmpDhA I like the Rob Schnieder ones better :-)

 

Plone secrets: Episode 3 – Collective Recaptcha installation

Another one from the: “wow, this approach is totally and completely non-obvious to beginners” department.

My kingdom for a (custom) contact form (with captcha)

I don’t know if I’ve made written-mention of this anywhere else, but aclark.net has a new customized contact form with captcha. ;-) It is customized via z3c.jbot which is an awesome tool (more on that later). This in and of itself is not-so-terribly newsworthy. What is interesting, though, is how this new customized form came to be; and how its features compare to the default contact form.

So here goes: In Plone, we have a page template called contact-info.cpt. It’s not so special (in that it is pretty feature-less, though it will send mail if you ask it to) but it does the job for most folks. And it almost has to, because customizing it is beyond the realm of what anyone would call “straight forward” or “reasonable to expect from TTW customizers, integrators, or even developers”¹.

Why do I say this?

Been there, done that: CMFFormController

Photo credit: Scott Beale / Laughing Squid

First, let me start with the technology that is used to implement the contact form. It’s called CMFFormController and it went out of style in the 1970s, along with disco and bell bottoms. Bell bottoms came back, but CMFFormController didn’t! Don’t get me wrong: CMFFormController is a decent technology/implementation. It works. But it’s not very “modern” by today’s coding standards. As such, it will simply be dragged along Plone-version-after-Plone-version until either: a.) someone wants to replace it, or b.) it becomes too big of a maintenance burden to support and someone has to replace it. This is the way of many things, and there is nothing inherently wrong with this phenomenon. In fact, there are even good things about it: e.g. the release manager, framework team, and core developers’ ability to publish release-after-solid-release under such code-aging circumstances is a testament to their skill and dedication.

BUT… and this is a BIG BUT.

We can do better

Leaving this old stuff laying around, with no new stuff to point new users to does a huge disservice to all of our users. It flies directly in the face of one of our core missions: as Wyn Williams put it once, to be the

“best damn enterprise content manage system on the planet”.

Now, I’ve been around the block, so I am not suggesting we must fix everything at once. Legacy software can be supported for years and years and years (and YEARS). What I am suggesting is that we need to make a very significant effort to COMPLETELY HIDE these implementation details to newcomers. I don’t want to tell people in IRC to go to portal_skins anymore. I want my “OS X Lion release for Plone”, please (sans Vista overtones.) :-)

So how do we get there? Well, in the case of portal_skins there is talk of decommissioning portal_view_customizations, which was supposed to be the “new portal_skins” as I understand it. But since half of our templates are still in CMF skin layers, and because this feature was not technically well received (i.e. it needs more features and development), and because portal_resources came along around the same time as plone.app.theming, folks are considering removing portal_view_customizations. I have no strong opinion about it (other than I hate the name, too long) and I trust the Framework Team to handle it. What I do care about is that whatever remains in the ZMI be very clearly designated as either “new style” or “old style”. We can’t get away from the ZMI yet, but portal tools do have title attributes so let’s use them.

Now, we can’t ditch portal_skins just yet, and who knows what will happen with portal_view_customizations, but the *minute* we know some technology is out of date, we should reveal it in the user interface (even in the ZMI user interface). E.g.:

Curiously, the attribute that holds this string is lowercase “title” (I’d expect camel case Description, though I’m not entirely sure why I expect that.)

Hanno Schlichting has made some great progress recently with enhancing the ZMI for Plone users, especially with regard to file-system vs. through-the-web development, and through-the-plone vs. through-the-zmi configuration, e.g.:

I love this trend, and would like to see more of it!

Secrets revealed

Anyway, I’ve been dancing around the secrets to be revealed in this blog post because it is fun to play with the future. And it’s important to work hard toward achieving it. But enough of that, here is what you need to know today.

Like I said, I customized the contact form.

Old style vs. new style

Back in the “old days” you had to create a CMF skin layer and put a copy of the template in a directory on the file system, configured as a File System Directory View. Everything used to be customized via skin layers.

Now-a-days, we have z3c.jbot. Though a bit of a hack², it does exactly what you’d expect, almost exactly how you’d expect it to. It doesn’t even require a Python package. By convention though, folks typically do put z3c.jbot template customizations in Python packages.

This requires a few steps.

Step 1: Create a Python package

First, a Python package. This is relatively simple, so I’m not going to skip-and-point-you-somewhere-else just yet, I’m going to explain first. The gist of it is this:

$ mkdir -p my.package/my/package
$ touch my.package/setup.py
$ touch my.package/my/__init__.py
$ touch my.package/my/package/__init__.py

Now you would edit setup.py and the “middle” __init__.py with code. Something like this:

#!/bin/sh
mkdir -p my.package/my/package
touch my.package/setup.py
touch my.package/my/__init__.py
touch my.package/my/package/__init__.py
cat > my.package/setup.py << EOF
from setuptools import setup, find_packages
setup(
    name='my.package',
    packages=find_packages(),
    namespace_packages=[
        'my',
    ]
)
EOF
cat > my.package/my/__init__.py << EOF
from pkg_resources import declare_namespace
declare_namespace(__name__)
EOF

Alternatively, use ZopeSkel to generate all this boilerplate code for you. It does a much better, and more complete job than what I have done here. The important thing is that you understand what is going on.

In the case of aclark.net, our Python package is called plonetheme.aclarknet.

Step 2: Add template overrides

Now that we have a Python package we can start customizing Plone. By convention, we  create a “templates” directory inside the namespaced package e.g.:

$ mkdir my.package/my/package/templates

Or you can check out aclark.net’s “templates” directory here:

Because of the way z3c.jbot works, in the “templates” directory, we add files with names that correspond to the Python module we want to customize. E.g.

(For some reason, github thinks that file is binary, so here are the contents.)

Now, this is the amazing part: in addition to templates in views, viewlets and portlets, we can customize any CMF object! E.g. the RestrictedPython (more technology anyone?) CMFFormController validation script used to validate our contact form:

That brings us to adding recaptcha, but first let us finish configuring template overrides.

Step 3: Configure template overrides

Now that we have customized Plone templates, we can configure Plone to use our customizations.

This is done via a technology you may have heard of: ZCML. Using ZCML, we can tell Plone (or jbot in this case) to use the templates in our “templates” directory.

The ZCML we are going to use is placed in the “top level” configure.zcml file in our package. That means we need a top level configure.zcml file:

$ touch my.package/my/package/configure.zcml

Next we add ZCML to “configure our application”. Note in addition to the ZCML used to configure jbot, there is ZCML for Diazo and ZCML to hold our Genericsetup customizations:

<configure
    xmlns:browser="http://namespaces.zope.org/browser"
    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
    xmlns:plone="http://namespaces.plone.org/plone"
    xmlns="http://namespaces.zope.org/zope">

    <plone:static directory="theme/aclarknet" type="theme" />

    <include package="z3c.jbot" file="meta.zcml" />
    <browser:jbot directory="templates" />

    <genericsetup:registerProfile
        name="default"
        title="ACLARK.NET, LLC profile"
        description="Installs ACLARK.NET, LLC site
            customizations"
        directory="profiles/default"
        provides="Products.GenericSetup.interfaces.EXTENSION"
        />

</configure>

This file is located here:

In order to see what is really going on, check out this diagram:

You can see that everything inside the <configure></configure> tag(s) is associated with an XML namespace. If you don’t add the appropriate namespace inside the <configure> tag, your configuration will fail spectacularly (because without the proper XML namespace configured, there is no code loaded to handle your configuration.)

Step 4: Add recaptcha

Now, finally, we get to the exciting part. We have customized our contact form, but we are receiving a fair amount of spam due to spammers’ ability to automate form submission. To foil the spammers, we want to add a captcha form that will hopefully require that an actual human to fill out the form.

Thanks to David Glick and Groundwire, we have collective.recaptcha which provides an integration of Google’s Recaptcha service into Plone.

In order to use it, first we add the package to our buildout, e.g.:

…
[plone]
# Eggs are Python packages
eggs +=
#   Diazo theming
    plonetheme.aclarknet
#   Add-ons
    collective.portlet.wordpress
    collective.recaptcha

# Need zcml for c.recaptcha until 1.1.3 is released
zcml = collective.recaptcha
…

See the rest of the file here:

Now run buildout and restart Plone.

With collective.recaptcha installed via buildout, you should now be able to open http://yoursite:8080/Plone/@@recaptcha-settings to configure Recaptcha:

 

 

(To get a public and private key, you can sign up for recaptcha here: http://www.google.com/recaptcha)

Lastly, make the appropriate changes to the contact form and validation script. E.g. include the captcha image:

…
<tal:block tal:replace="structure
    context/@@captcha/image_tag"/>
…

And make sure to validate the submission:

…
    # Re-captcha validation
    if not context.restrictedTraverse('@@captcha').verify():
        context.plone_utils.addPortalMessage(_(u'You entered
            an invalid captcha.'), 'error')
        return state.set(status='failure')
    else:
        return state
…

That’s it!

 Notes

¹ I’m pushing “reasonable” limits here for argument’s sake. For those who know Plone already, a lot of what might seem impossible to newcomers is “reasonable” for them. No flames please. Unless you absolutely must. ;-)

² I hear people call it that, though I don’t know the details. I assume it “monkey patches” which template to use at render-time.