[Zope3-Users] stuck with zope.schema.List and subwidget
Christian Lueck
christian.lueck at ruhr-uni-bochum.de
Mon Aug 29 13:15:38 EDT 2005
Stephan Richter schrieb:
>
> The problem, I think (actually I just checked, so I know ;-), is that
> CustomWidgetFactory was not designed to work well with advanced widgets, i.e.
> widgets that have more constructor arguments beyond the field and the
> request.
>
Hm, so you think :-) I should rather use CustomSequenceWidgetFactory?
No, that doesn't work ether. (Still the same error, still don't know what to pass to 'fields'.)
But I got an other solution/suggestion: Redefine the constructor of
zope.app.form.browser.sequencewidget.SequenceWidget in new classes, say
CustomSequenceWidget and CustomListSequenceWidget. They work together
with CustomWidgetFactory (pretty) well:
from zope.app.form.browser.sequencewidget import SequenceWidget, ListSequenceWidget
class CustomSequenceWidget(SequenceWidget):
def __init__(self, context, request, subwidget=None):
super(SequenceWidget, self).__init__(context, request)
self.subwidget = subwidget
class CustomListSequenceWidget(ListSequenceWidget):
def __init__(self, context, request, subwidget=None):
super(SequenceWidget, self).__init__(context, request)
self.subwidget = subwidget
And then defining tuple/sequence-widgets like this:
tuplex_widget = CustomWidgetFactory(CustomSequenceWidget, subwidget=objectx_w)
listx_widget = CustomWidgetFactory(CustomListSequenceWidget, subwidget=objectx_w)
This way I got the poll-example of zope/app/form/browser/widget.txt
working, which did not work out of the box. Besides this bigger change there had
to be added some minor changes, espesially in configure.zcml
I suggest to add the two above classes to
zope/app/form/browser/sequencewidget.py
Regards
Christian
The poll-example:
----------------------------------------------------
interfaces.py
----------------------------------------------------
from zope.interface import Interface
from zope.schema import Object, Tuple, TextLine
from zope.schema.interfaces import ITextLine
from zope.i18n import MessageIDFactory
_ = MessageIDFactory("poll")
class IPollOption(Interface):
label = TextLine(
title=u'Label',
min_length=1)
description = TextLine(
title=u'Description',
min_length=1)
class IPoll(Interface):
options = Tuple(
title=u'Options',
value_type=Object(schema=IPollOption,
title=u'Poll Option'))
def getResponse(option):
"get the response for an option"
def choose(option):
'user chooses an option'
----------------------------------------------------
poll.py
----------------------------------------------------
from persistent import Persistent
from interfaces import IPoll, IPollOption
from zope.interface import implements, classImplements
class PollOption(Persistent, object):
implements(IPollOption)
class Poll(Persistent, object):
implements(IPoll)
def getResponse(self, option):
return self._responses[option]
def choose(self, option):
self._responses[option] += 1
self._p_changed = 1
def get_options(self):
return self._options
def set_options(self, options):
self._options = options
self._responses = {}
for option in self._options:
self._responses[option.label] = 0
options = property(get_options, set_options, None, 'fiddle options')
----------------------------------------------------
browser.py
----------------------------------------------------
from zope.app.form.browser.editview import EditView
from zope.app.form.browser.add import AddView
from zope.app.form import CustomWidgetFactory
from zope.app.form.browser import SequenceWidget, ObjectWidget
from interfaces import IPoll, IPollOption
from poll import Poll, PollOption
class PollVoteView:
__used_for__ = IPoll
def choose(self, option):
self.context.choose(option)
self.request.response.redirect('.')
class CustomSequenceWidget(SequenceWidget):
def __init__(self, context, request, subwidget=None):
super(SequenceWidget, self).__init__(context, request)
self.subwidget = subwidget
ow = CustomWidgetFactory(ObjectWidget, PollOption)
sw = CustomWidgetFactory(CustomSequenceWidget, subwidget=ow)
class PollEditView(EditView):
__used_for__ = IPoll
options_widget = sw
class PollAddView(AddView):
__used_for__ = IPoll
options_widget = sw
----------------------------------------------------
configure.zcml
----------------------------------------------------
<configure xmlns='http://namespaces.zope.org/zope'
xmlns:browser='http://namespaces.zope.org/browser'>
<content class=".poll.Poll">
<!-- <factory id="zope.app.demo.poll" /> This path seems wrong. We don't needa factory as it is
identical with the content-class. -->
<implements
interface="zope.app.annotation.interfaces.IAttributeAnnotatable"
/>
<require
permission="zope.View"
interface=".interfaces.IPoll"
/>
<require
permission="zope.ManageContent"
set_schema=".interfaces.IPoll"
/>
</content>
<content class=".poll.PollOption">
<require
permission="zope.View"
interface=".interfaces.IPollOption"
/>
</content>
<browser:page for=".interfaces.IPoll"
name="index.html"
template="results.zpt"
permission="zope.View"
menu="zmi_views" title="View"
/>
<browser:pages
for=".interfaces.IPoll"
class=".browser.PollVoteView"
permission="zope.ManageContent">
<browser:page
name="vote.html"
template="vote.zpt"
menu="zmi_views" title="Vote"
/>
<browser:page
name="choose"
attribute="choose" />
</browser:pages>
<browser:addform
schema=".interfaces.IPoll"
label="Add a Poll"
content_factory=".poll.Poll"
name="AddPoll.html"
class=".browser.PollAddView"
permission="zope.ManageContent"
/>
<!--
<browser:addMenuItem
title="Poll Demo"
description="Poll Demo"
content_factory=".poll.Poll"
view="AddPoll.html"
permission="zope.ManageContent"
/>
-->
<browser:addMenuItem
class=".poll.Poll"
title="Poll Demo"
description="Poll Demo"
view="AddPoll.html"
permission="zope.ManageContent"
/>
<browser:editform
schema=".interfaces.IPoll"
class=".browser.PollEditView"
label="Change a Poll"
name="edit.html"
menu="zmi_views" title="Edit"
permission="zope.ManageContent"
/>
</configure>
----------------------------------------------------
vote.zpt
----------------------------------------------------
<html metal:use-macro="context/@@standard_macros/page">
<title metal:fill-slot="title">Poll voting</title>
<div metal:fill-slot="body">
<form action="choose">
<table border="1">
<caption>Poll voting</caption>
<tbody>
<tr tal:repeat="option context/options">
<td><input type="radio" name="option"
tal:attributes="value option/label"></td>
<td tal:content="option/label">Option</td>
<td tal:content="option/description">Option</td>
</tr>
</tbody>
</table>
<input type="submit">
</form>
</div>
</html>
----------------------------------------------------
results.zpt
----------------------------------------------------
<html metal:use-macro="context/@@standard_macros/page">
<title metal:fill-slot="title">Poll results</title>
<div metal:fill-slot="body">
<table border="1">
<caption>Poll results</caption>
<thead>
<tr><th>Option</th><th>Results</th><th>Description</th></tr>
</thead>
<tbody>
<tr tal:repeat="option context/options">
<td tal:content="option/label">Option</td>
<td tal:content="python:context.getResponse(option.label)">Result</td>
<td tal:content="option/description">Option</td>
</tr>
</tbody>
</table>
</div>
</html>
More information about the Zope3-users
mailing list