[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