我希望能够在 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。我试图从不同的地方触发表单#2,例如 DispatcherView(BrowserView) call () 方法,表单#1 的call () 方法,还有后者的 update() 和 render() 但所有这些覆盖都会导致同样的问题。
搭载连续呼叫的合适位置在哪里,这样这个东西就可以工作了,还是我需要创建单独的页面并使用 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中查看slug:
<browser:page
name="view"
for="Products.myproduct.DispatcherView"
class=".file.DispatcherView"
permission="zope2.View"
/>