In modifying the formdemo/addressbook example to use groups, I found
that fields in groups are not cleared to their default values when the
Done or Delete button is pressed in the editform, resulting in an
addform with values from the previous editform. Fields that are not in
groups are cleared (as in the original example, which had no groups);
only fields in groups have this problem. How can I fix this? And more
generally, how are widgets cleared?
Relevant code is attached. The editform class is below.
thanks!
-------
class CarEditForm(group.GroupForm,form.EditForm):
form.extends(group.GroupForm,form.EditForm)
noChangesMessage = None
fields = field.Fields(ICar).select('nPassengers')
groups=(carGroup1,)
prefix = 'car.edit.'
@button.buttonAndHandler(u'Delete')
def handleDelete(self, action):
# Delete the item from the address book
item = self.getContent()
addressbook = item.__parent__
del addressbook[item.__name__]
# Reset the selected item
ISession(self.request)[SESSION_KEY]['selectedItem'] = None
@button.buttonAndHandler(u'Done')
def handleDone(self, action):
# Reset the selected item
ISession(self.request)[SESSION_KEY]['selectedItem'] = None
-------
import zope.component
import zope.location
from zope.app.container import btree
from zope.session.interfaces import ISession
from zope.pagetemplate.interfaces import IPageTemplate
from zope.publisher.browser import BrowserPage
from zope.publisher import browser
from zope.traversing.browser import absoluteURL
from zope.viewlet.viewlet import CSSViewlet, JavaScriptViewlet
from z3c.template.interfaces import ILayoutTemplate
from zc.table import column
from zc.table.interfaces import ISortableColumn
from z3c.form import form, field, button, subform, group
from interfaces import *
from classes import Car
import formatter
import zope.component
SESSION_KEY = 'z3c.formdemo.addressbook'
AddressBookCSSViewlet = CSSViewlet('addressbook.css')
TextShadowViewlet = JavaScriptViewlet('text-shadow.js')
class AddForm(form.AddForm):
form.extends(form.AddForm)
def create(self, data):
newItem = self.klass(**data)
return newItem
def add(self, object):
count = 0
while '%s-%i' %(self.itemName,count) in self.context:
count += 1;
self._name = '%s-%i' %(self.itemName,count)
self.context[self._name] = object
return object
def nextURL(self):
return self.request.getURL()
class SelectColumn(column.GetterColumn):
zope.interface.implements(ISortableColumn)
def renderCell(self, item, formatter):
value = super(SelectColumn, self).renderCell(item, formatter)
return '<a href="%s?select%s=%s">%s</a>' %(
formatter.request.getURL(), self.itemType.capitalize(), item.__name__, value)
class CarAddForm(group.GroupForm,AddForm):
form.extends(AddForm)
fields = field.Fields(ICar).select('nPassengers')
groups=(carGroup1,)
prefix = 'car.add.'
klass=Car
itemName='car'
AddCarLabel = button.StaticButtonActionAttribute(
u'Add Car', button=form.AddForm.buttons['add'], form=CarAddForm)
class CarEditForm(group.GroupForm,form.EditForm):
form.extends(group.GroupForm,form.EditForm)
noChangesMessage = None
fields = field.Fields(ICar).select('nPassengers')
groups=(carGroup1,)
prefix = 'car.edit.'
@button.buttonAndHandler(u'Delete')
def handleDelete(self, action):
# Delete the item from the address book
item = self.getContent()
addressbook = item.__parent__
del addressbook[item.__name__]
# Reset the selected item
ISession(self.request)[SESSION_KEY]['selectedItem'] = None
@button.buttonAndHandler(u'Done')
def handleDone(self, action):
# Reset the selected item
ISession(self.request)[SESSION_KEY]['selectedItem'] = None
class SelectCarColumn(SelectColumn):
itemType='car'
class AddressBook(BrowserPage):
@apply
def selectedItem():
def get(self):
session = ISession(self.request)[SESSION_KEY]
return session.get('selectedItem')
def set(self, value):
session = ISession(self.request)[SESSION_KEY]
session['selectedItem'] = value
return property(get, set)
def update(self):
# Select a new item
path=self.request['PATH_INFO']
if 'selectCar' in self.request:
self.selectedItem = self.context[self.request['selectCar']]
elif self.selectedItem and not ICar.providedBy(self.selectedItem):
self.selectedItem=None
# Setup the form
if self.selectedItem:
self.form = CarEditForm(self.selectedItem, self.request)
self.form.update()
if not self.selectedItem:
self.form = CarAddForm(self.context, self.request)
self.form.update()
# Setup the table
rows = [
content for content in self.context.values()
if ICar.providedBy(content)]
columns=(
SelectCarColumn(u'the make', lambda i, f: i.make, name='make'),
SelectCarColumn(u'the model', lambda i, f: i.model, name='model'),
)
self.table = formatter.SelectedItemFormatter(
self.context, self.request, rows,
prefix = SESSION_KEY + '.', columns=columns,
sort_on=[(columns[0].name, False)])
self.table.sortKey = 'z3c.formdemo.addressbook.sort-on'
self.table.cssClasses['table'] = 'item-list'
self.table.widths = (120,)*len(columns)
self.table.selectedItem = self.selectedItem
def __call__(self):
self.update()
layout = zope.component.getMultiAdapter((self, self.request),
ILayoutTemplate)
return layout(self)
class AddressBook(BrowserPage):
@apply
def selectedItem():
def get(self):
session = ISession(self.request)[SESSION_KEY]
return session.get('selectedItem')
def set(self, value):
session = ISession(self.request)[SESSION_KEY]
session['selectedItem'] = value
return property(get, set)
def update(self):
# Select a new item
path=self.request['PATH_INFO']
if 'selectCar' in self.request:
self.selectedItem = self.context[self.request['selectCar']]
elif self.selectedItem and not ICar.providedBy(self.selectedItem):
self.selectedItem=None
# Setup the form
if self.selectedItem:
self.form = CarEditForm(self.selectedItem, self.request)
self.form.update()
if not self.selectedItem:
self.form = CarAddForm(self.context, self.request)
self.form.update()
# Setup the table
rows = [
content for content in self.context.values()
if ICar.providedBy(content)]
columns=(
SelectCarColumn(u'the make', lambda i, f: i.make, name='make'),
SelectCarColumn(u'the model', lambda i, f: i.model, name='model'),
)
self.table = formatter.SelectedItemFormatter(
self.context, self.request, rows,
prefix = SESSION_KEY + '.', columns=columns,
sort_on=[(columns[0].name, False)])
self.table.sortKey = 'z3c.formdemo.addressbook.sort-on'
self.table.cssClasses['table'] = 'item-list'
self.table.widths = (120,)*len(columns)
self.table.selectedItem = self.selectedItem
def __call__(self):
self.update()
layout = zope.component.getMultiAdapter((self, self.request),
ILayoutTemplate)
return layout(self)
from zope.interface import implements
from zope.app.container.contained import Contained
from zope.security.proxy import removeSecurityProxy
from zope.schema.fieldproperty import FieldProperty
from interfaces import ICar
class Car(Contained):
implements(ICar)
def __init__(self, **data):
for key,val in data.items():
setattr(self,key,val)
def __str__(self): return '%s %s'%(self.make,self.model)
def __repr__(self): return '%s %s'%(self.make,self.model)
make = FieldProperty(ICar['make'])
model = FieldProperty(ICar['model'])
nPassengers = FieldProperty(ICar['nPassengers'])
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:z3c="http://namespaces.zope.org/z3c"
i18n_domain="addressbook"
>
<z3c:template
template="addressbook.pt"
for=".browser.AddressBook"
layer="z3c.formdemo.layer.IDemoBrowserLayer"
/>
<browser:zrt-resource
name="addressbook.css"
file="addressbook.css"
layer="z3c.formdemo.layer.IDemoBrowserLayer"
/>
<browser:viewlet
name="addressbook.css"
view=".browser.AddressBook"
manager="z3c.formdemo.skin.ICSS"
class=".browser.AddressBookCSSViewlet"
permission="zope.Public"
layer="z3c.formdemo.layer.IDemoBrowserLayer"
weight="1000"
/>
<browser:zrt-resource
name="text-shadow.js"
file="text-shadow.js"
layer="z3c.formdemo.layer.IDemoBrowserLayer"
/>
<browser:viewlet
name="text-shadow.js"
view=".browser.AddressBook"
manager="z3c.formdemo.skin.IJavaScript"
class=".browser.TextShadowViewlet"
permission="zope.Public"
layer="z3c.formdemo.layer.IDemoBrowserLayer"
/>
<class class=".classes.Car">
<allow interface=".interfaces.ICar" />
<require
permission="zope.Public"
set_schema=".interfaces.ICar" />
</class>
<z3c:pagelet
name="car.html"
for="zope.app.container.interfaces.IContainer"
class=".browser.AddressBook"
layer="z3c.formdemo.layer.IDemoBrowserLayer"
permission="zope.Public"
/>
<adapter
factory=".browser.AddCarLabel"
name="title" />
<utility
provides="zope.app.schema.vocabulary.IVocabularyFactory"
component=".vocabulary.carsInParent"
name="allCars"
/>
</configure>
from zope.interface import Interface
from zope.schema import Field, Text, TextLine, Choice, Int, Bool, Date, Datetime, Object, List
from z3c.form import field, group
class ICar(Interface):
make = TextLine(
title = u'make',
description = u'make',
default = u'',
required = False)
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 carGroup1(group.Group):
label = u'carGroup1'
fields = field.Fields(ICar).select(
'make','model'
)
from zope.schema.vocabulary import SimpleVocabulary
from interfaces import ICar
def carsInParent(context):
'''returns car subobjects of parent as a vocabulary'''
container=context.__parent__ or context
return SimpleVocabulary.fromItems(
[('%s %s'%(v.make,v.model), v) for k, v in container.items() if ICar.providedBy(v)])
_______________________________________________
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users