我希望能够一个接一个地在Plone中链接多个z3c表单.例如,一旦form#1完成处理并完成错误检查,它将结果(最好通过GET变量)传递给form#2,这反过来又对form#3等…我也想能够对所有表单使用相同的URL.
我当前的实现是拥有一个浏览器视图,然后该浏览器视图将调度适当的表单,即DispatcherView检查self.request变量,然后确定要调用form#1,form#2,form#3中的哪一个.
我有这段代码,但z3c表单似乎抽象为对BrowserView的多次调用,并且尝试触发从它对z3c.form的多次调用会干扰对后者的处理.例如,当用户按下一次“提交”按钮时,将对表单#1进行错误检查,而当我尝试以下示例中的解决方案时,表单#2返回的结果显示所有必填字段均不正确,这意味着表单#2接收了来自表格#1.我试图从不同的地方触发form#2,例如DispatcherView(BrowserView)call()方法,form#1的call()方法,后者的update()和render(),但是所有这些替代都会导致同样的问题.
piggy带连续调用的合适位置在哪里,这样就可以工作,还是我需要创建单独的页面并使用self.request.RESPONSE.redicrect显式地彼此重定向?
from Products.Five import BrowserView
from zope import interface, schema
from z3c.form import form, field, group, button
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
countries = SimpleVocabulary([SimpleTerm(value="not_selected", title=_("Chose your region")),
SimpleTerm(value="canada", title=_("Canada")),
SimpleTerm(value="us", title=_("United States")),
SimpleTerm(value="belgium", title=_("Belgium"))])
products = SimpleVocabulary([SimpleTerm(value="product1", title=_("Product1")),
SimpleTerm(value="product2", title=_("Product2")),
SimpleTerm(value="product3", title=_("Product2"))
])
class DispatcherView(BrowserView):
def __call__(self):
if 'form.widgets.region' in self.request.keys():
step2 = Step2(self.context, self.request)
return step2.__call__()
else:
step1 = Step1(self.context, self.request)
return step1.__call__()
def update(self):
pass
class IStep1(interface.Interface):
region = schema.Choice(title=_("Select your region"),
vocabulary=countries, required=True,
default="not_selected")
class IStep2(interface.Interface):
product = schema.Choice(title=_("Pick a product"),
vocabulary=products, required=True)
class Step1(form.Form):
fields = field.Fields(IStep1)
def __init__(self,context, request):
self.ignoreContext = True
super(self.__class__, self).__init__(context, request)
def update(self):
super(self.__class__, self).update()
@button.buttonAndHandler(u'Next >>')
def handleNext(self, action):
data, errors = self.extractData()
if errors:
print "Error occured"
class Step2(form.Form):
fields = field.Fields(IStep2)
def __init__(self,context, request):
self.ignoreContext = True
super(self.__class__, self).__init__(context, request)
def update(self):
super(self.__class__, self).update()
@button.buttonAndHandler(_('<< Previous'))
def handleBack(self, action):
data, errors = self.extractData()
if errors:
print "Error occured"
#handle input errors here
@button.buttonAndHandler(_('Next >>'))
def handleNext(self, action):
data, errors = self.extractData()
if errors:
print "Error occured"
编辑:
克里斯·尤因(Cris Ewing)给出了答案,这是示例示例代码在使用Collective.z3cformwizard重写后的样子:
from zope import schema, interface
from zope.interface import implements
from z3c.form import field, form
from collective.z3cform.wizard import wizard
from plone.z3cform.fieldsets import group
from plone.z3cform.layout import FormWrapper
from Products.statusmessages.interfaces import IStatusMessage
from Products.statusmessages.adapter import _decodeCookieValue
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from z3c.form.browser.checkbox import CheckBoxFieldWidget
from Products.Five import BrowserView
countries = SimpleVocabulary([SimpleTerm(value="not_selected", title=_("Chose your region")),
SimpleTerm(value="belgium", title=_("Belgium")),
SimpleTerm(value="canada", title=_("Canada")),
SimpleTerm(value="us", title=_("United States")),
])
products = SimpleVocabulary([SimpleTerm(value="product1", title=_("Product1")),
SimpleTerm(value="product2", title=_("Product2")),
SimpleTerm(value="product3", title=_("Product3")),
SimpleTerm(value="product4", title=_("Product4")),
SimpleTerm(value="product5", title=_("Product5"))
])
class Step1(wizard.Step):
prefix = 'one'
fields = field.Fields(schema.Choice(__name__="region",
title=_("Select your region"), vocabulary=countries,
required=True, default="not_selected")
)
class Step2(wizard.Step):
prefix = 'two'
fields = field.Fields(schema.List(__name__="product",
value_type=schema.Choice(
title=_("Select your product"),
vocabulary=products),
required=True
)
)
for fv in fields.values():
fv.widgetFactory = CheckBoxFieldWidget
class WizardForm(wizard.Wizard):
label= _("Find Product")
steps = Step1, Step2
def finish(self):
##check answer here
import pdb; pdb.set_trace()
class DispatcherView(FormWrapper):
form = WizardForm
def __init__(self, context, request):
FormWrapper.__init__(self, context, request)
def absolute_url(self):
return '%s/%s' % (self.context.absolute_url(), self.__name__)
也不要忘记在configure.zcml中使用browser:view slug:
<browser:page
name="view"
for="Products.myproduct.DispatcherView"
class=".file.DispatcherView"
permission="zope2.View"
/>
解决方法:
我认为您正在寻找这个:
http://pypi.python.org/pypi/collective.z3cform.wizard