2012-05-10 34 views
3

我希望能夠在Plone中依次鏈接幾個z3c表單。例如,一旦表單#1完成了處理並完成了錯誤檢查,它將結果(最好通過GET變量)傳遞到表單#2,而表單#3又形成#3等等。我也想成爲能夠爲所有表單使用相同的URL。鏈接z3c表格

我目前的實現是有一個瀏覽器視圖,然後調度適當的形式,即DispatcherView檢查self.request變量,然後確定哪個形式#1,形式#2,形式#3調用。

我有這個代碼,但似乎z3c表單被抽象爲多次調用BrowserView,並試圖從它觸發多個調用到z3c.form干擾後者的處理。例如,當用戶按下「提交」按鈕一次,表單#1的錯誤檢查發生,當我在下面的例子中嘗試解決方案時,表單#2返回顯示所有必填字段不正確,這意味着#2表單從形式#1。我試圖從不同的地方觸發形式#2,如DispatcherView(BrowserView)調用()方法,調用()方法的形式#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" 

編輯: 克里斯尤文給了這個答案,這裏的代碼看起來怎麼樣等之後,它已經使用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" 
/> 

回答

3
+0

謝謝,這是非常接近我所需要的。一個簡單的問題是,是否有可能保持會話周圍,然後有一個自定義的最終頁面,用戶可以從這些頁面進入任何步驟並編輯它們,然後直接返回到最終頁面? –

+0

順便說一句,是否可以有條件的步驟,或者我需要廣泛修改嚮導以添加此功能? –