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

Reply via email to