Michael Howitz wrote:
The motivation is the following:
self.getContent() seems to be the pattern to access the context of a form. I used grep: there is no place where self.context is used directly besides in group.py. So it seems to be an error in the code not to use the common pattern. But after reading the doctests of z3c.form I'm no longer sure whether this is correct.
My use case is the following:
I have a folder with contained items. In a form I display the schema of the folder in the group form and the schemas of all contained items as groups. Each group has a nested group displaying the meta data for the group's content. As the context of the groups was the folder (group = groupClass(self.context, self.request, self)) the meta data displayed was wrong.
But if your Groupform override getContent to provide an object implementing the expected interface, that's right
Class IAddress(Interface): street = zope.schema.TextLine( title='street')
Class IPerson(Interface); firstname = zope.schema.TextLine( title='firstname')
address = zope.schema.Object( title='address', schema = IAddress)
class Address(object): implements(IAddress)
def __init__(self, **kw): for name, value in kw.items(): setattr(self, name, value)
class Person(object): implements(IPerson)
def __init__(self, **kw): for name, value in kw.items(): setattr(self, name, value)
class AddressGroup(group.Group): label = 'Address' fields = field.Fields(zope.schema.TextLine( __name__ = 'owner', title='Owner', readOnly=True) fields += field.Fields(IAddress).select('street')
def getContext(self):
Should be "getContent", I think.
return { 'owner': self.context.firstname, 'street': self.context.address.street}
class PersonGroup(group.Group): label = 'Person' fields += field.Fields(IPerson).select('firstname')
class PersonEditForm(group.GroupForm, form.EditForm): fields = field.Fields(zope.schema.TextLine( __name__="description', title='Description', readOnly=True) groups = (PersonGroup, AddressGroup)
def getContent(self): return {'description': 'Form used to edit a person and its Address'}
I had never seen this before but according to the doctests of z3c.form it is a valid use case.
My understand of ``getContent`` is to provide a way to give values used by the widgets. By default, since the common use case is to edit / display values from the context, the implementation return the context. If your form has to deal with fields defined in an interface not provided by the context, you have a lot of ways to provides the related values. * The first one is to provide an adapter adapting the context to the interface defining the field * The second one is to override the ``getContent`` implementation so it'll return an object implementing the right interface * The thirds one is to override the ``getContent`` implementation so it'll return a dictionary where key = field.__name__ and value = the value expected by the field. (In fact a default adapter exist that adapt a dict to an interface) * ... Have a look to datamanager.txt....
class MyEditForm(group.GroupForm, form.EditForm):
def __init__(self, context, request): super(MyEditForm, self).__init__(context, request) firstContext = {} secondContext = {} self.groups = ( MyFirstGroup(firstcontext, request, self), MySecondGroup(secondContext, request, self))
I'm not sure whether this works. (I'll try it.) Whether it works it obsoletes my changes.
According to the z3c.form implemention, the right place to put your subform initialization is into the ``update`` method. class MyEditForm(group.GroupForm, form.EditForm): def update(self): self.groups = ( MyFirstGroup(self.context.obj1, request, self), MySecondGroup(self.context.obj2, request, self)) super(MyEditForm,self).update() Yours sincerely, sagblmi