Building A Simple Search Interface
Understanding Formlib
zope.formlib is a Zope 3 package designed to ease the development of web-based forms in your Zope applications. In its simplest form you can compare what it does with the auto-generated displays Archetypes provides you for viewing a content type (base_view) and editing a content type (base_edit). For all practical sense formlib based components are really regular Zope view components with some convenient base classes for auto-generating output based on schema's and other configuration info.
Thankfully beginning with Zope 2.9.3 zope.formlib is now being distributed with Zope 2. Of course Five >= 1.4 is required to make use of this Zope 3 package.
Defining Our First Form
For purposes of this writing we will construct a very simple search form for searching Plone content. This form will be similar to Plone's built in advanced search form but much simpler.
You can view the working source code of these examples at the updated collective svn browser and updated collective svn repository locations.
The Form Class
We begin by creating a new file, browser.py, which will need to live in ploneexample.formlib/ploneexample/formlib/. The browser.py file will comprise the bulk of the necessary work. Lets start by adding the necessary imports.
from zope import interface, schema from zope.formlib import form from Products.CMFCore import utils as cmfutils from Products.Five.browser import pagetemplatefile from Products.Five.formlib import formbase
Next we'll construct our first Zope 3 interface:
class ISearch(interface.Interface):
text = schema.TextLine(title=u'Search Text',
description=u'The text to search for',
required=False)
description = schema.TextLine(title=u'Description',
required=False)
The purpose of the interface in this case is not to describe a particular content object but instead to define the fields that formlib will use. Later on we'll discover how tradtional interfaces used to describe actual content classes can be used in combination with formlib to autogenerate proper add and edit forms for content.
And now for the form view class itself. We will start with the first part of the class definition.
class SearchForm(formbase.PageForm):
form_fields = form.FormFields(ISearch)
result_template = pagetemplatefile.ZopeTwoPageTemplateFile('search-results.pt')
We use the PageForm class as our super class to inherit functionality from formlib itself. By default, PageForm knows how to generate all the HTML that will make up of our finished form. But in order to do this, formlib needs to know what fields we want. We do this by providing the form_fields attribute. FormFields is a formlib helper class that generates the appropriate field items from any Zope 3 schema (in this case, the schema interface we just defined).
The result_template attribute defines a new page template that we will use to iterate over all of the results of our search.
Next we define an action for our form:
@form.action("search")
def action_search(self, action, data):
catalog = cmfutils.getToolByName(self.context, 'portal_catalog')
kwargs = {}
if data['text']:
kwargs['SearchableText'] = data['text']
if data['description']:
kwargs['description'] = data['description']
self.search_results = catalog(**kwargs)
self.search_results_count = len(self.search_results)
return self.result_template()
This is where the real work takes place. A formlib action is generally a handler that will somehow get invoked by submitting an HTML form. In this case we create a new action labeled search, that will be used to handle when a user hits the search button. Our formlib-based class will automatically understand how to hook in an search button on the HTML form itself. This particular action handler will return our result template as a result.
The Result Page Template
In order to display the results of our search form we need to setup a simple page template. We will name this template, search-results.pt. Most the of template is pretty uninteresting. But for purposes of this writing we will demonstrate the result printing portion.
<tal:block tal:repeat="single view/search_results">
<div class="single-result">
<h4>
<span tal:replace="repeat/single/number"></span>.
<a tal:content="single/Title" tal:attributes="href single/getURL" href=""></a>
</h4>
<p tal:content="single/Description"></p>
</div>
</tal:block>
Since our previous formlib based class was a regular view, it gets treated that way inside the page templates. And we are able to assign simple attributes to our view that can get picked up within the template.
Tying It All Together With ZCML
Now that we've defined the form class and the result page template to go along with it we need to glue this all into Zope. We do this in configure.zcml.
So we need to add the appropriate ZCML snippet:
<browser:page
name="search.html"
for="Products.CMFPlone.Portal.PloneSite"
class=".browser.SearchForm"
permission="zope.Public"
/>
Keen readers will notice the special name for configuring the new view component, browser:page. This XML tag actually employs an XML namespace prefix which needs to be defined. Normally this is added right onto the configure tag like this:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:five="http://namespaces.zope.org/five">
Double-check the configure.zcml file if there are any doubts to the configuration.
Again, since formlib is all based on regular Zope 3 view components, we register them the same way in the ZCML. For those of you unfamiliar with Zope 3 view components, these particular snippets basically mean that the search.html view will be available directly from the plone site, so the url would look something like this: http://localhost:8080/plonesite1/search.html
- Search Form

- Search Results

Our First zope.formlib Example In Summary
The example demonstrated here shows the simplest form that could be created with formlib and how to hook in a simple action. It should be obvious from this example how you could use formlib to replace simple CMFFormController based logic. Of course formlib can do many other advanced things such as provide sub-form functionality and autogenerated add and edit forms for content classes.
The bottom line is that zope.formlib is ready for use inside Plone today. And since formlib is so easy to work with, the author recommends all Plone application developers give it a try.

Author: