Z3c chains

I would like to be able to chain multiple z3c forms in Plone one by one. For example, as soon as form No. 1 completes processing and completes error checking, it passes the results (preferably through GET variables) to form No. 2, which, in turn, does the same with form No. 3, etc. I would also like to be able to use the same URL for all forms.

My current implementation is to have a browser view that then submits the appropriate forms, that is, DispatcherView checks the self.request variables, and then determines which form # 1, form No. 2, form No. 3 to call.

I have this code, but it seems that z3c forms are abstracted as multiple calls to BrowserView, and trying to initiate multiple calls from it to z3c.form interferes with processing the latter. For example, when the user clicks the submit button once, error # 1 is checked, and when I try to find a solution in the example below, form # 2 returns, showing that all required fields are incorrect, which means that form # 2 I got the values ​​from form No. 1. I tried to call form # 2 from different places, such as the DispatcherView (BrowserView) call () method, the call () method of form # 1, as well as update () and render () of the latter, but all of these overrides lead to the same problem.

Where is the appropriate place for consecutive calls for this to work, or do I need to create separate pages and explicitly redirect to each other using 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: Chris Ewing answered this question, what does the sample code look like after overwriting it with the collect.z3cformwizard command:

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__)

Also don't forget the browser: look at slug in the configure.zcml file:

<browser:page
    name="view"
    for="Products.myproduct.DispatcherView"
    class=".file.DispatcherView"
    permission="zope2.View"
/>
+3
source share
1 answer
+3
source

All Articles