2012-05-10 1 views
3

Я хотел бы иметь возможность цепочки нескольких 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" 
/> 

ответ

3

Я думаю, что вы ищете это:

http://pypi.python.org/pypi/collective.z3cform.wizard

+0

Спасибо, что очень близко к тому, что мне нужно. Быстрый вопрос: можно ли проводить сеанс вокруг, а затем иметь пользовательскую конечную страницу, с которой пользователь может перейти на любой из этапов и отредактировать их, а затем вернуться непосредственно на финальную страницу? –

+0

Кстати, можно ли иметь условные шаги или мне нужно активно модифицировать мастер, чтобы добавить эту функциональность? –

 Смежные вопросы

  • Нет связанных вопросов^_^