Re: SVN: z3c.form/trunk/ ``GroupForm`` and ``Group`` now use ``getContent`` method when instantiating group classes instead of directly accessing ``self.context``, as this is the usual way to access the context of the form and allows nested groups to have a different context than the main form.

Laurent Mignon <[email protected]>
Newsgroups gmane.comp.web.zope.devel
Message-ID <[email protected]>
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


_______________________________________________
Zope-Dev maillist  -  [email protected]
https://mail.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 https://mail.zope.org/mailman/listinfo/zope-announce
 https://mail.zope.org/mailman/listinfo/zope )
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.