Last modified: May 02, 2025 By Alexander Williams

Custom Forms in Plone with z3c.form

Plone is a powerful CMS built on Python. It offers flexibility through custom forms. The z3c.form library makes form creation easy.

This guide covers the basics of z3c.form. You'll learn to build, customize, and manage forms in Plone.

Why Use z3c.form in Plone?

z3c.form is the standard form library for Plone. It integrates well with Plone's architecture. It simplifies complex form handling.

Key benefits include automatic rendering, validation, and data conversion. It works with Plone's security system. It supports both simple and complex forms.

Setting Up Your Environment

Before starting, ensure Plone is installed. Follow our Plone setup guide if needed.

Add z3c.form to your buildout.cfg:


[instance]
eggs =
    Plone
    z3c.form

Creating a Basic Form

Start by creating a simple form. First, define a schema interface. This describes your form fields.


from zope import schema
from zope.interface import Interface

class IMyForm(Interface):
    """Form schema interface"""
    name = schema.TextLine(
        title=u"Name",
        required=True
    )
    email = schema.TextLine(
        title=u"Email",
        required=True
    )

Next, create the form class. Inherit from z3c.form.form.Form.


from z3c.form import form, button
from plone.z3cform.layout import wrap_form

class MyForm(form.Form):
    fields = field.Fields(IMyForm)
    ignoreContext = True
    
    @button.buttonAndHandler(u"Submit")
    def handleSubmit(self, action):
        data, errors = self.extractData()
        if errors:
            return
        # Process valid data here

Rendering the Form

To display the form, wrap it in a view. Use Plone's standard template wrapper.


MyFormView = wrap_form(MyForm)

Register the view in ZCML:


<browser:page
    name="my-form"
    for="*"
    class=".forms.MyFormView"
    permission="zope2.View"
    />

Adding Form Validation

z3c.form provides built-in validation. You can add custom validators too.


from z3c.form import validator

class EmailValidator(validator.SimpleFieldValidator):
    def validate(self, value):
        super(EmailValidator, self).validate(value)
        if '@' not in value:
            raise schema.ValidationError(u"Invalid email")

Register the validator:


validator.WidgetValidatorDiscriminators(
    EmailValidator,
    field=IMyForm['email']
)

Customizing Form Display

Control how forms look using templates. Learn more in our Plone templates guide.

Override the default template:


from z3c.form.interfaces import IFormLayer

class MyFormTemplate(LayoutTemplateFactory):
    template = ViewPageTemplateFile('templates/mytemplate.pt')

Working with Content Types

Forms often interact with content. See our content models guide for details.

Here's how to edit content:


from plone.dexterity.interfaces import IDexterityContent

class EditForm(form.EditForm):
    fields = field.Fields(IMyForm)
    ignoreContext = False

Advanced Form Features

z3c.form supports many advanced features:

  • Dynamic fields
  • Subforms
  • Wizards
  • AJAX handling

Common Issues and Solutions

Problem: Form not rendering. Solution: Check ZCML registration and template paths.

Problem: Validation not working. Solution: Ensure validators are properly registered.

Problem: Permission errors. Solution: Verify the form's permission settings.

Conclusion

z3c.form is powerful for Plone form development. It handles both simple and complex cases well.

Start with basic forms, then explore advanced features. Combine with other Plone components for best results.

For more Plone development tips, see our Python developer guide.