Add a simple form¶
Description
A simple tutorial introducing the basics of Plone development.
In this tutorial we add a simple form.
There are many ways to add a form to Plone. In this tutorial, we use z3c.form.
There are two steps to building a simple z3c.form form; registering the form in configure.zcml, and writing the Python code to handle the form.
Register the form¶
To register our form, we need to add an entry in configure.zcml.
-
Edit the configure.zcml file in the browser directory. Open configure.zcml in your editor and add this just before the closing </configure> tag.:
<browser:page name="hello_world_form" for="*" permission="zope2.View" class=".hello_world_form.HelloWorldFormView" />
Note
- We use the name attribute to access the form.
- The for attribute allows us to limit context to a particular interface. With the asterisk, we are not limiting access.
- The permission attribute allows us to limit access with a permission. In this case, we have a wide open permission.
- The class attribute points to our Python class. Here, we have a HelloWorldFormView class in a file named hello_world_form.py.
Our entry uses the browser prefix, so we need to define it in configure.zcml before we can use it.
-
Add xmlns:browser="http://namespaces.zope.org/browser" at the top of configure.zcml so it looks something like:
<configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="example.helloworld">
When we are done, configure.zcml should look something like this.:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="example.helloworld">
<include package="plone.app.contentmenu" />
<!-- -*- extra stuff goes here -*- -->
<browser:page
name="hello_world_form"
for="*"
permission="zope2.View"
class=".hello_world_form.HelloWorldFormView"
/>
</configure>
Python code¶
Now we need to create the code to handle our form.
-
create the file hello_world_form.py in the browser directory.:
touch hello_world_form.py
Open the hello_world_form.py file in your editor and add the following code.
-
Define our form field in an interface.
The imports:
from zope.interface import Interface from zope.schema import TextLine from zope.i18nmessageid import MessageFactory _ = MessageFactory('hello_world')
The interface:
class IHelloWorldForm(Interface): hello_world_name = TextLine( title=_(u'Name'), description=_(u'Please enter your name.'), required=False)
This defines a TextLine field with an id of hello_world_name. The title and description will show up on the form. It is not a required field.
-
Create a class for our logic. This is used when our view is accessed.
The imports:
from Products.statusmessages.interfaces import IStatusMessage from z3c.form import button from z3c.form import form, field
The class:
class HelloWorldForm(form.Form): fields = field.Fields(IHelloWorldForm) ignoreContext = True def updateWidgets(self): super(HelloWorldForm, self).updateWidgets() @button.buttonAndHandler(u'Save') def handleSave(self, action): data, errors = self.extractData() if errors: return False if data['hello_world_name'] is not None: hello_name = data['hello_world_name'] else: hello_name = 'World' IStatusMessage(self.request).addStatusMessage( "Hello %s" % hello_name, 'info') redirect_url = "%s/@@hello_world_form" % self.context.absolute_url() self.request.response.redirect(redirect_url) @button.buttonAndHandler(u'Cancel') def handleCancel(self, action): IStatusMessage(self.request).addStatusMessage( "Hello No One", 'info') redirect_url = "%s/@@hello_world_form" % self.context.absolute_url() self.request.response.redirect(redirect_url)
Note
- We first import the field from our interface above.
- The ignoreContext directive means this form is not meant to be called in the context of an object.
- We define updateWidgets to the same method belonging to our parent.
- We create 2 button handlers.
The fun parts here are the two button handlers; handleSave and handleCancel.
-
At the bottom of hello_world_form.py we need to use wrap_form on our class. This wraps our form in the standard Plone layout, placing our form in the content area. This also creates the view HelloWorldFormView referenced in configure.zcml.:
from plone.z3cform.layout import wrap_form HelloWorldFormView = wrap_form(HelloWorldForm)
Access the form¶
You can access the form with an url like:
http://localhost:8080/Plone/@@hello_world_form
Type in a name and click Save, or just click Cancel.