A variation on my previous z3c.form example

Another example of form logic, adding to the one discussed in my previous post.

Here is the idea: If you need a more flexible solution for your use case, you can inherit directly from z3c.form.form.Form.
Let’s say you want the form to be used for both adding contact information (making sure later that this only works when the user is authenticated) and sending a mail message to the site administrator. A site feedback form that will at the same time be used to populate your database of contacts.

Your form class could be defined as follows (I’m skipping the imports part):

# my.example/my/example/browser.py class ContactForm(z3c.form.form.Form): """ Contact Form """ fields = z3c.form.field.Fields(interfaces.IContactData) message_field = z3c.form.field.Fields(schema.TextLine(__name__ = 'message', title=u"Message", required=False) ) fields += message_field ignoreContext = True @z3c.form.button.buttonAndHandler(u'Send', name='send') def handle_send(self, action): data, errors = self.extractData() if errors: self.status = z3c.form.form.EditForm.formErrorsMessage return # Add the contact data, if not in yet id = data['firstname'] + data['lastname'] id = zope.component.queryUtility(IIDNormalizer).normalize(id) if id not in self.context.objectIds(): self._name = id contact = MyContact(self._name, **data) self.context[self._name] = contact # Do something else, e.g. send the message to the site admin. # Complete the code as needed... message = data['message'] print "Message from %s %s (%s):\n%s" % (data['firstname'], data['lastname'], data['email'], data['message']) # Redirect self.request.RESPONSE.redirect(self.context.absolute_url())

The main points of the used pattern:

  • You define the fields for the form ; new fields can be added to the already defined list (based on the IContactData schema in interfaces.py) using the “+” operator.
  • You define your specific form button(s) and handler method(s). In the case of a standard AddForm, there is already a handle_add() defined for the “add” button for you.
  • Also, you need to set the form attribute ‘ignoreContext’ to True, so that the form has the same behaviour as an AddForm, i.e. it does not have to get/set data on attributes on the context. Note that by default, an AddForm has this attribute set to True, and an EditForm has it set to False.

Now, the final touch with the wrapping view…

class ContactFormView(base.FormWrapper): form = ContactForm label= "Contact Form"

… and its configuration:

<configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" xmlns:five="http://namespaces.zope.org/five" i18n_domain="my.example" > <browser:page for="Products.CMFPlone.Portal.PloneSite" name="contact_form" class=".browser.ContactFormView" permission="zope2.View" /> </configure>

One Response to A variation on my previous z3c.form example

  1. […] With the small API changes that happened, you can see below that there is less to write to expose the form in the Plone site (our ContactForm example from my previous post): […]

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: