More on using the EditForm

September 17, 2008

I now better understand this after reading z3c.form’s doctests: If the context object that you want to edit fulfills the interface used for your EditForm, the code for defining the form class could be as small as this (followed by the usual configure.zcml snippet):

class ContactEditForm(z3c.form.form.EditForm): """ Contact Edit Form """ fields = z3c.form.field.Fields(IContactData) # For wrapping the form presentation within Plone's layout ContactEditFormView = layout.wrap_form(ContactEditForm, label="Edit Form")

If it does not, you get an error as the framework finds that the object does not match the schema or there is not an adapter to it.

The solution in such a case is to define an adapter to the interface, and override the getContent() method of the form to give the adapted object to the EditForm so it can do its job on it, i.e. update it.

Here is an example with an ATDocument used as the context.

class ContactAdapter(object): zope.component.adapts(IATDocument) zope.interface.implements(IContactData) def __init__(self, document): self.document = document @apply def lastname(): def get(self): return getTheLastname(self.document) def set(self, value): setTheLastname(self.document, value) return property(get, set)
class ContactEditForm(z3c.form.form.EditForm): """ Contact Edit Form """ fields = z3c.form.field.Fields(IContactData) def getContent(self): '''See interfaces.IForm''' return IContactData(self.context)

This approach is valid for cases where you don’t want to introduce a new content type. Hopefully, there will be a time when introducing a new type would be easier, not require too much things to change, and not add complexity to your Plone site with the risk of maintenance issues. (I’m thinking plone.dexterity here.) Then, things should be straightforward.

You can find the detailed code of my z3c.form usage examples in the
example.z3cform package in the Collective.

Update: Do not forget to register the Adapter in the configure.zcml. (Thx to Gilles for informing me that I forgot to mention this bit.)

<adapter factory=”.adapter.ContactAdapter” />