Я хотел бы иметь возможность цепочки нескольких z3c-форм в Plone один за другим. Например, как только форма №1 завершает обработку и завершает проверку ошибок, она передает результаты (предпочтительно через переменные GET) в форму №2, которая, в свою очередь, делает то же самое с формой № 3 и т. Д. Я также хотел бы быть способный использовать один и тот же URL для всех форм.Цепочки z3c формы
Моей текущей реализацией является просмотр браузера, который затем отправляет соответствующие формы, то есть DispatcherView проверяет переменные self.request и затем определяет, какая из форм # 1, форма №2, форма №3 для вызова.
У меня есть этот код, но кажется, что формы z3c абстрагируются как несколько вызовов BrowserView, и попытка инициировать несколько вызовов от него до z3c.form мешает обработке последнего. Например, когда пользователь нажимает кнопку «отправить» один раз, происходит проверка ошибок формы №1, и когда я пытаюсь найти решение в примере ниже, форма # 2 возвращает, показывая, что все обязательные поля являются неправильными, что означает, что форма №2 получила значения из форма № 1. Я попытался вызвать форму # 2 из разных мест, таких как DispatcherView (BrowserView) call() method, call() метод формы # 1, а также 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"
EDIT: Cris Юинг дал ответ на это, вот как пример кода выглядит после того, как она была переписана с использованием 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:page
name="view"
for="Products.myproduct.DispatcherView"
class=".file.DispatcherView"
permission="zope2.View"
/>
Спасибо, что очень близко к тому, что мне нужно. Быстрый вопрос: можно ли проводить сеанс вокруг, а затем иметь пользовательскую конечную страницу, с которой пользователь может перейти на любой из этапов и отредактировать их, а затем вернуться непосредственно на финальную страницу? –
Кстати, можно ли иметь условные шаги или мне нужно активно модифицировать мастер, чтобы добавить эту функциональность? –