[Zope3-Users] want to use ObjectWidget and default add form

john saponara john at saponara.net
Thu Jan 3 22:48:46 EST 2008


thanks christophe.  while looking for an example of how to use 
CustomWidgetFactory, i found a comment on the web about formlib 
replacing browser:editform/addform (at 
http://faassen.n--tree.net/blog/view/weblog/2005/09/06/0) and so i'm now 
using the instructions in zope/formlib/form.txt.  unfortunately i still 
had to customize the car widget to avoid an error.  for the car widget, 
i want to let the user select from the list of all car objects in the 
parent 'limoService' container, but when i do i get the error "Not 
enough context information to get parent" at the getParent call.  my 
custom widget is:

from zope.app.form.browser.widget import SimpleInputWidget
class CarsListWidget(SimpleInputWidget):
    def cars(self):
       parent=zapi.getParent(self.context)
       return [name for name,child in parent.items() if 
ICar.providedBy(child)]
    def __call__(self):
       return '\n'.join([
          '<select name="%s" class="option-list">' % ('car'),
          '\n'.join(['\t<option>%s</option>' % (car) for car in 
self.cars()]),
          '</select>',
          ])

and the full error (when trying to edit driver 'd1' via 'd1/edit.html') is:

2008-01-03T21:56:05 ERROR SiteError 
http://localhost:2020/mylimo/d1/edit.html
Traceback (most recent call last):
   File "C:\Python24\Lib\site-packages\zope\publisher\publish.py", line 
133, in publish
     result = publication.callObject(request, obj)
   File 
"C:\Python24\Lib\site-packages\zope\app\publication\zopepublication.py", 
line 161, in callObject
     return mapply(ob, request.getPositionalArguments(), request)
   File "C:\Python24\Lib\site-packages\zope\publisher\publish.py", line 
108, in mapply
     return debug_call(obj, args)
    - __traceback_info__: <security proxied 
zope.app.pagetemplate.simpleviewclass.SimpleViewClass from 
C:\pr\z3\lib\python\limoService\edit.pt instance at 0x0210EE50>
   File "C:\Python24\Lib\site-packages\zope\publisher\publish.py", line 
114, in debug_call
     return obj(*args)
   File "C:\Python24\Lib\site-packages\zope\formlib\form.py", line 770, 
in __call__
     return self.render()
   File "C:\Python24\Lib\site-packages\zope\formlib\form.py", line 764, 
in render
     self.form_result = self.template()
   File 
"C:\Python24\Lib\site-packages\zope\app\pagetemplate\viewpagetemplatefile.py", 
line 83, in __call__
     return self.im_func(im_self, *args, **kw)
   File 
"C:\Python24\Lib\site-packages\zope\app\pagetemplate\viewpagetemplatefile.py", 
line 51, in __call__
     sourceAnnotations=getattr(debug_flags, 'sourceAnnotations', 0),
   File 
"C:\Python24\Lib\site-packages\zope\pagetemplate\pagetemplate.py", line 
117, in pt_render
     strictinsert=0, sourceAnnotations=sourceAnnotations)()
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
271, in __call__
     self.interpret(self.program)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
861, in do_defineMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
909, in do_extendMacro
     definingName, extending)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
891, in do_useMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
536, in do_optTag_tal
     self.do_optTag(stuff)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
521, in do_optTag
     return self.no_tag(start, program)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
516, in no_tag
     self.interpret(program)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
861, in do_defineMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
957, in do_defineSlot
     self.interpret(block)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
949, in do_defineSlot
     self.interpret(slot)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
861, in do_defineMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
861, in do_defineMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
957, in do_defineSlot
     self.interpret(block)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
957, in do_defineSlot
     self.interpret(block)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
861, in do_defineMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
957, in do_defineSlot
     self.interpret(block)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
534, in do_optTag_tal
     self.no_tag(stuff[-2], stuff[-1])
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
516, in no_tag
     self.interpret(program)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
824, in do_loop_tal
     self.interpret(block)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
534, in do_optTag_tal
     self.no_tag(stuff[-2], stuff[-1])
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
516, in no_tag
     self.interpret(program)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
861, in do_defineMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
861, in do_defineMacro
     self.interpret(macro)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
346, in interpret
     handlers[opcode](self, args)
   File "C:\Python24\Lib\site-packages\zope\tal\talinterpreter.py", line 
745, in do_insertStructure_tal
     structure = self.engine.evaluateStructure(expr)
   File "C:\Python24\Lib\site-packages\zope\tales\tales.py", line 696, 
in evaluate
     return expression(self)
    - C:\Python24\Lib\site-packages\zope\formlib\pageform.pt
    - Line 128, Column 14
    - Expression: <PathExpr standard:u'widget'>
    - Names:
       {'args': (),
        'context': <limoService.classes.Driver object at 0x021F16D0>,
        'default': <object object at 0x00A3C568>,
        'loop': {},
        'nothing': None,
        'options': {},
        'repeat': {},
        'request': <zope.publisher.browser.BrowserRequest instance 
URL=http://localhost:2020/mylimo/d1/edit.html>,
        'template': 
<zope.app.pagetemplate.viewpagetemplatefile.ViewPageTemplateFile object 
at 0x020BF3F0>,
        'usage': <zope.pagetemplate.pagetemplate.TemplateUsage object at 
0x020FA2B0>,
        'view': <zope.app.pagetemplate.simpleviewclass.SimpleViewClass 
from C:\pr\z3\lib\python\limoService\edit.pt object at 0x0210EE50>,
        'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper 
object at 0x020FAA30>}
   File "C:\Python24\Lib\site-packages\zope\tales\expressions.py", line 
217, in __call__
     return self._eval(econtext)
   File "C:\Python24\Lib\site-packages\zope\tales\expressions.py", line 
211, in _eval
     return ob()
   File "C:\pr\z3\lib\python\limoService\classes.py", line 41, in __call__
     return '\n'.join([
   File "C:\pr\z3\lib\python\limoService\classes.py", line 37, in cars
     parent=zapi.getParent(self.context)
   File "C:\Python24\Lib\site-packages\zope\traversing\api.py", line 
140, in getParent
     raise TypeError("Not enough context information to get parent", obj)
TypeError: ('Not enough context information to get parent', 
<zope.schema._field.Object object at 0x0210ECF0>)
127.0.0.1 - - [3/Jan/2008:21:56:05 -0400] "GET /mylimo/d1/edit.html 
HTTP/1.1" 500 84 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; 
rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11"

and my complete code is:

############################
# interfaces.py

from zope.interface import Interface
from zope.schema import Field, Text, TextLine, Choice, Int, Bool, Date, 
Datetime, Object
from zope.schema.vocabulary import SimpleVocabulary

from zope.app.container.constraints import ContainerTypesConstraint
from zope.app.container.constraints import ItemTypePrecondition
from zope.app.container.interfaces import IContained, IContainer

class ICar(Interface):

    model = TextLine(
       title = u'model',
       description = u'model',
       default = u'',
       required = False)
    nPassengers = Int(
       title = u'nPassengers',
       description = u'nPassengers',
       default = 0,
       required = False)

class IDriver(Interface):

    car = Object(
       title = u'car',
       description = u'car',
       default = None,
       schema=ICar,
       required = False)

class ILimoservice(IContainer):
    '''container for items of type ICar, IDriver'''
    name = TextLine(
       title=u'Limoservice',
       description=u'a Limoservice container',
       default=u'',
       required=True)
    def __setitem__(name, obj): pass
    __setitem__.precondition = ItemTypePrecondition(ICar, IDriver)
class ILimoserviceContained(IContained):
    '''for types that can only be contained in a Limoservice'''
    __parent__ = Field(constraint = ContainerTypesConstraint(ILimoservice))

############################
# classes.py

from zope.app import zapi
from zope.interface import implements
from zope.app.container.btree import BTreeContainer
from zope.app.container.contained import Contained

from limoService.interfaces import ICar, IDriver, ILimoservice, 
ILimoserviceContained

class Car(Contained):
    implements(ICar,ILimoserviceContained)
    model = u''
    nPassengers = 0

class Driver(Contained):
    implements(IDriver,ILimoserviceContained)
    car = None

class Limoservice(BTreeContainer):
    implements(ILimoservice)
    name = "u''"

class CarView(object):
     def message(self):
         return '%s holds %d passengers' % (
            self.context.model, self.context.nPassengers)
class DriverView(object):
    def message(self):
       if self.context.car:
          carInfo=self.context.car.__dict__
       else:
          carInfo=None
       return 'driver drives car model %s' % (carInfo)

from zope.app.form.browser.widget import SimpleInputWidget
class CarsListWidget(SimpleInputWidget):
    def cars(self):
       parent=zapi.getParent(self.context)
       return [name
          for name,child in parent.items() if ICar.providedBy(child)]
    def __call__(self):
       return '\n'.join([
          '<select name="%s" class="option-list">' % ('car'),
          '\n'.join(
             ['\t<option>%s</option>' % (car)
                for car in self.cars()]),
          '</select>',
          ])

from zope.formlib import form
class CarEdit(form.EditForm):
    form_fields = form.Fields(ICar)
class DriverEdit(form.EditForm):
    form_fields = form.Fields(IDriver)
    form_fields["car"].custom_widget = CarsListWidget

############################
# configure.zcml

<configure
     xmlns="http://namespaces.zope.org/zope"
     xmlns:browser="http://namespaces.zope.org/browser"
	i18n_domain="limoService"
	>
	
   <interface
       interface=".interfaces.ICar"
       type="zope.app.content.interfaces.IContentType"
       />
   <interface
       interface=".interfaces.IDriver"
       type="zope.app.content.interfaces.IContentType"
       />

   <class class=".classes.Car">
     <implements
         interface="zope.annotation.interfaces.IAttributeAnnotatable"
         />
     <factory
         id="limoService.classes.Car"
         description="a car"
         />
     <require
         permission="zope.Public"
         interface=".interfaces.ICar"
         />
     <require
         permission="zope.ManageContent"
         set_schema=".interfaces.ICar"
         />
   </class>
   <class class=".classes.Driver">
     <implements
         interface="zope.annotation.interfaces.IAttributeAnnotatable"
         />
     <factory
         id="limoService.classes.Driver"
         description="a driver"
         />
     <require
         permission="zope.Public"
         interface=".interfaces.IDriver"
         />
     <require
         permission="zope.ManageContent"
         set_schema=".interfaces.IDriver"
         />
   </class>

   <browser:addMenuItem
       class=".classes.Car"
       title="a car"
       permission="zope.ManageContent"
       description='add Car'
   />
   <browser:addMenuItem
       class=".classes.Driver"
       title="a driver"
       permission="zope.ManageContent"
       description='add Driver'
   />

   <browser:page
       for=".classes.Car"
       name="index.html"
       class=".classes.CarView"
       permission="zope.Public"
	  template='read.pt'
       />
   <browser:page
       for=".classes.Driver"
       name="index.html"
       class=".classes.DriverView"
       permission="zope.Public"
	  template='read.pt'
       />

   <browser:page
       for=".classes.Car"
       name="edit.html"
       class=".classes.CarEdit"
       permission="zope.ManageContent"
       template="edit.pt"
       />
   <browser:page
       for=".classes.Driver"
       name="edit.html"
       class=".classes.DriverEdit"
       permission="zope.ManageContent"
       template="edit.pt"
       />

   <interface
       interface=".interfaces.ILimoservice"
       type="zope.app.content.interfaces.IContentType"
       />

   <class class=".classes.Limoservice">
     <implements
         interface="zope.app.annotation.interfaces.IAttributeAnnotatable"
         />
     <implements
         interface="zope.app.container.interfaces.IContentContainer"
         />
     <factory
         id="limoService.classes.Limoservice"
         description="Limoservice"
         />
     <require
         permission="zope.ManageContent"
         interface=".interfaces.ILimoservice"
         />
     <require
         permission="zope.ManageContent"
         set_schema=".interfaces.ILimoservice"
         />
   </class>

   <browser:addMenuItem
       class=".classes.Limoservice"
       title="Limoservice"
       permission="zope.ManageContent"
   />
   <browser:containerViews
       for="limoService.interfaces.ILimoservice"
       index="zope.View"
       contents="zope.View"
       add="zope.ManageContent"
       />

   </configure>

############################
# read.pt

<html metal:use-macro="context/@@standard_macros/view">
<body>
<div metal:fill-slot="body">
   <big tal:content="python: view.message()"></big>
</div>
</body>
</html>

############################
# edit.pt

<html metal:use-macro="context/@@standard_macros/view">
<body>
<div metal:fill-slot="body" tal:content="view">
</div>
</body>
</html>



Christophe Combelles wrote:
> john saponara a écrit :
>> hi,
>>
>> please point me to an example showing how to use ObjectWidget with a 
>> default add form.  in case there is no example, perhaps my failing 
>> attempt below could serve as one, once it's modified to work.
> 
> [...]
> 
>> ComponentLookupError: ((<zope.schema._field.Object object at 
>> 0x03584090>, <zope.publisher.browser.BrowserRequest instance 
>> URL=http://localhost:2020/mylimo/@@+/action.html>), <InterfaceClass 
>> zope.app.form.interfaces.IInputWidget>, u'') 127.0.0.1 - - 
> 
> It seems you have no widget associated to your Object field.
> You should use less zcml and implement your own addform:
> 
>   driver_widget = CustomWidgetFactory(ObjectWidget, Driver)
> 
>   class DriverAddForm(AddForm):
>     form_fields = Fields(IDriver)
>     form_fields['car'].custom_widget = driver_widget
>     def __init__(self, context, request):
>         (...)
>     def create(self.data):
>         (...)
> 
> Christophe
> _______________________________________________
> Zope3-users mailing list
> Zope3-users at zope.org
> http://mail.zope.org/mailman/listinfo/zope3-users



More information about the Zope3-users mailing list