跳转到主要内容

这是一个使用z3c.form创建多页向导的库。值在向导完成前存储在会话中。

项目描述

简介

该库实现了一个简单的基于z3c.form的向导。向导由多个步骤组成。每个步骤都是一个表单。数据在用户点击最后一个步骤上的完成按钮之前存储在会话中。

为了充分利用这个库,您首先需要对z3c.form有合理的了解。以下是一些开始的地方

向导步骤

向导步骤是一个带有一些额外功能的正常z3c.form表单。

默认情况下,此表单访问的内容将是向导会话中的一个字典,其键等于步骤的前缀。

其他属性

wizard

此步骤正在使用的向导。

available

布尔值,表示当前步骤是否可以通过向导导航链接访问。默认情况下,只有已经存储在会话中的数据的步骤可以访问。(无论此属性的值如何,都可以通过相应的按钮访问下一个和上一个步骤。)

completed

布尔值,表示是否允许用户进入下一个步骤。默认为True。如果为False,则“继续”按钮将被禁用。

cssid

字符串。为表单标签提供的用户定义的CSS id。

其他方法

applyChanges(data)

将此步骤的更改保存到其内容(通常是向导会话中的PersistentDict)。

load(context)

根据上下文加载此步骤的会话数据。

apply(context)

根据此步骤的会话数据更新上下文。

向导组步骤

与向导步骤相同;它只是像z3c.form GroupForm一样处理一组组。

其他属性

groups

您希望以单独的字段集显示在表单中的组列表。

向导

向导也是一个表单,其中包含步骤列表和在这些步骤之间移动的内置逻辑。

类属性。重写这些属性以影响向导的行为

steps

当调用向导的更新方法时将实例化的步骤类序列。

sessionKey

返回此向导实例使用的唯一会话键。默认情况下,这是“collective.z3cform.wizard”和向导的URL路径的元组。

在更新方法期间设置的属性

activeSteps

一系列向导步骤实例。

currentStep

当前正在显示的向导步骤实例。

currentIndex

当前步骤在activeSteps序列中的(基于0)索引。

session

在此向导中持久化数据会话。

onFirstStep

布尔值。如果是向导的第一个步骤正在显示,则为True。

onLastStep

布尔值。如果是向导的最后一个步骤正在显示,则为True。

allStepsFinished

布尔值。如果每个向导步骤的“available”属性为True,则为True。

finished

布尔值。如果向导已经完成,则为True。

absolute_url

向导的URL。

validate_back

布尔值。如果您想当用户在步骤上使用“后退”按钮时验证向导的输入,则为True。如果不这样做,则放弃所有用户输入(数据)。默认行为是True。[Spanky]

方法

initialize()

在给定会话中第一次查看向导时调用。

此方法可以用于将数据从某些来源填充到会话中。

默认实现调用loadSteps方法。

loadSteps(context)

从上下文加载向导会话数据。

默认实现调用每个向导步骤的“load”方法。

finish()

在成功完成向导并在验证最后一个步骤之后调用。

使用此方法执行一些基于在完成向导期间填写的数据的操作。

默认实现调用applySteps方法。

applySteps(context)

根据向导会话数据更新上下文。

默认实现调用每个向导步骤的“apply”方法。

sync()

将会话标记为已更改,以确保更改得到持久化。这是必需的,因为我们没有使用持久化感知字典类来处理我们的会话变量。

兼容性

此包已在Zope 2.10与Plone 3.3,以及Zope 2.12与Plone 4中进行测试。

在其他由z3c.form支持的平台上使用它应该相当简单,例如Zope 3,但需要熟悉这些环境的人告诉我如何处理会话,例如。

致谢

此包受到了集体.singing包中包含的基于非会话的z3c.form向导的启发,该向导由Daniel Nouri实现。

会话支持、其他改进和重新打包由David Glick完成。

还要感谢Nathan van Gheem、Laurence Rowe和Tom “Spanky” Kapanka。

变更日志

1.4.8 (2013-04-18)

  • 修复了适用于Plone 4.3的pagetemplate导入。[jone]

  • 添加了中文翻译。[jianaijun]

  • 现在清除操作会更新活动步骤(需要覆盖动态向导)[gotcha, schminitz]

  • 修复了动态向导中步骤数据的初始加载情况(例如,当步骤依赖于用户数据时)[gotcha, schminitz]

  • 在子类中启用覆盖按钮条件。[gotcha]

  • 在wizard.Wizard中,如果self.__name__为None,则absolute_url属性将抛出TypeError。不再是这样了!现在的问题是在那种情况下absolute_url将不准确。待办事项[spanky]

  • 添加了法语翻译。[mpeeters]

1.4.7 (2012-01-05)

  • 添加了使用Back按钮跳过当前输入验证的能力。默认设置保持不变。[spanky]

  • 将“id”作为表单标签的属性。[spanky]

1.4.6 (2011-10-19)

  • 添加了西班牙语翻译。[davisagli]

1.4.5 (2011-10-19)

  • 确保向导步骤标签已翻译。[davisagli]

1.4.4 (2011-10-17)

  • 避免使用any()以恢复与Python 2.4的兼容性。[davisagli]

1.4.3 (2011-07-13)

  • 在确定用户是否已离开向导时,不计入浏览器视图。[davisagli]

1.4.2 (2011-05-04)

  • 修复了AutoWizard小部件遍历器的注册。[elro]

1.4.1 (2011-05-04)

  • 添加了与plone.autoform一起使用的AutoWizard。[elro]

  • 添加了一个清除按钮,该按钮清除会话并返回到步骤1。[elro]

  • 重新排序按钮,使完成和继续都出现在后退之前。[elro]

1.4 (2011-05-04)

  • 删除<hr />[elro]

  • 使用Products.statusmessages。[elro]

  • 调整wizard-buttons以符合标准plone formControls。[elro]

  • 从wizard-step.pt中删除div.row。[elro]

1.3.3 (2011-03-22)

  • 在比较URL时标准化@@视图前缀。[davisagli]

1.3.2 (2010-07-27)

  • 删除多余的调试语句。[khink]

1.3.1 (2010-06-28)

  • 避免在plone.app.z3cform的行内验证期间破坏会话。[davisagli]

1.3 (2010-06-23)

  • 避免在安装plone.app.z3cform的行内验证时出错。[davisagli]

1.2 (2010-04-08)

  • 添加了一个GroupStep,用于类似于GroupForm的集成。[vangheem]

1.1 (2010-03-01)

  • 确保如果步骤通过按Enter键提交,则下一步按钮是默认的。

1.0 (2010-01-19)

  • 在表单标签中包含表单的enctype。

  • 在遍历表单到其他事物(如小部件)时不要清除会话。

1.0b2(2009-06-25)

  • 将默认向导CSS移动到浏览器资源,该资源可用但默认情况下不会引入。

  • 调整完成按钮的可见性标准,以便在所有步骤的数据都存储在会话中时,它将显示在任何步骤上。以前它只显示在最终步骤上。

  • 添加了向导导航,列出了向导的步骤,并链接到可用的步骤。

  • 在Wizard类中添加了对基于请求中传递的索引跳转到特定步骤的支持(但只有当该步骤可用时)。

  • 调整触发会话无效化的URL检查,以便不关注查询字符串或片段。

  • 将Wizard类的updateCurrentStep方法(不是公共API的一部分)更改为接受单个参数,即目标步骤索引。

  • 向Wizard类添加了‘allStepsFinished’属性。

  • 向Step类添加了‘available’属性。

  • 向Wizard类添加了‘absolute_url’属性。

  • 如果您在完成之前离开,请重置向导会话。

1.0b1 (2009-05-12)

  • 初始发布

示例和测试

定义包含三个步骤的向导

要定义一个使用向导的表单,我们需要定义步骤。这些步骤代表被顺序处理的单个表单。只有当最后一个步骤完成后,数据将通过用户定义的方法提交。

>>> from zope import schema
>>> from z3c.form import field, form
>>> from collective.z3cform.wizard import wizard
>>> from plone.z3cform.fieldsets import group
>>> from Products.statusmessages.interfaces import IStatusMessage
>>> from Products.statusmessages.adapter import _decodeCookieValue
>>> class StepOne(wizard.Step):
...     prefix = 'one'
...     fields = field.Fields(
...         schema.Int(__name__='age', title=u"Age"))

默认情况下,步骤将在会话中获取/设置值。如果我们想在向导完成后初始化这些值或对它们进行某些操作,我们需要为我们的步骤实现加载和应用方法。

>>> from pprint import pprint
>>> class StepTwo(wizard.Step):
...     prefix = 'two'
...     fields = field.Fields(
...         schema.TextLine(__name__='name', title=u"Name", required=True),
...         schema.TextLine(__name__='beer', title=u'Favorite Beer', required=True))
...
...     def load(self, context):
...         data = self.getContent()
...         data['name'] = 'David'
...
...     def apply(self, context):
...         data = self.getContent()
...         pprint('Name from step 2: %s' % data['name'])

我们还可以进行分组步骤

>>> class AddressGroup(group.Group):
...   fields = field.Fields(
...     schema.TextLine(__name__='address', title=u'Address', required=False),
...     schema.TextLine(__name__='city', title=u'City', required=False),
...     schema.TextLine(__name__='state', title=u'State', required=False))
...   label = u"Address Information"
...   prefix = 'address'
>>> class StepThree(wizard.GroupStep):
...   prefix = 'three'
...   fields = field.Fields()
...   groups = [AddressGroup]

现在我们可以定义我们的最小向导

>>> class Wizard(wizard.Wizard):
...     label = u"My silly wizard"
...     steps = StepOne, StepTwo, StepThree

渲染表单

现在让我们第一次渲染表单

>>> request = TestRequest()
>>> wizard = Wizard(None, request)
>>> print wizard()
<...
<div class="form" id="wizard-step-one">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="one" enctype="multipart/form-data">
      <p class="discreet"></p>
      <div class="field">
        <label for="one-widgets-age">
          <span>Age</span>
        </label>...
        <span class="fieldRequired"
              title="Required">
          (Required)
        </span>
        <div class="widget">
          <input id="one-widgets-age" name="one.widgets.age"
                 class="text-widget required int-field" value=""
                 type="text" />
        </div>
      </div>
  <div class="formControls wizard-buttons">
      <input id="form-buttons-continue"
             name="form.buttons.continue"
             class="submit-widget button-field" value="Continue"
             type="submit" />
      <input id="form-buttons-clear"
             name="form.buttons.clear"
             class="submit-widget button-field" value="Clear"
             type="submit" />
  </div>
  </form>
</div>

提交时出现错误

请记住,我们的第一步需要年龄。

>>> request.form = {
...     'form.buttons.continue': u'Continue',
... }
>>> wizard = Wizard(None, request)
>>> print wizard()
<...
...Required input is missing...
>>> messages = _decodeCookieValue(request.__annotations__.pop('statusmessages'))
>>> [(m.message, m.type) for m in messages]
[(u'There were errors.', u'error')]

成功提交第一步

>>> request.form['one.widgets.age'] = u'27'
>>> wizard = Wizard(None, request)
>>> print wizard()
<...
<div class="form" id="wizard-step-two">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="two" enctype="multipart/form-data">
      <p class="discreet"></p>
      <div class="field">
        <label for="two-widgets-name">
          <span>Name</span>
        </label>
        <span class="fieldRequired"
              title="Required">
          (Required)
        </span>
        <div class="widget">
          <input id="two-widgets-name" name="two.widgets.name"
                 class="text-widget required textline-field"
                 value="David" type="text" />
        </div>
      </div>
      <div class="field">
        <label for="two-widgets-beer">
          <span>Favorite Beer</span>
        </label>
        <span class="fieldRequired"
              title="Required">
          (Required)
        </span>
        <div class="widget">
          <input id="two-widgets-beer" name="two.widgets.beer"
                 class="text-widget required textline-field"
                 value="" type="text" />
        </div>
      </div>
    <div class="formControls wizard-buttons">
      <input id="form-buttons-continue" name="form.buttons.continue"
             class="submit-widget button-field" value="Continue"
             type="submit" />
      <input id="form-buttons-back" name="form.buttons.back"
             class="submit-widget button-field" value="Back"
             type="submit" />
      <input id="form-buttons-clear"
             name="form.buttons.clear"
             class="submit-widget button-field" value="Clear"
             type="submit" />
    </div>
  </form>
</div>

后退

当我们后退时,我们应该得到验证错误,因为我们留下了一个字段为空

>>> del request.form['form.buttons.continue']
>>> request.form['form.buttons.back'] = u'Back'
>>> wizard = Wizard(None, request)
>>> print wizard()
<...
...Required input is missing...
>>> messages = _decodeCookieValue(request.__annotations__.pop('statusmessages'))
>>> [(m.message, m.type) for m in messages]
[(u'There were errors.', u'error')]

现在如果我们把 validate_back 设置为 False,应该可以无错误地后退

>>> request.form['form.buttons.back'] = u'Back'
>>> wizard = Wizard(None, request)
>>> wizard.validate_back = False
>>> html = wizard()
>>> 'wizard-step-one' in html
True

确保我们回到第二步(再次)

>>> del request.form['form.buttons.back']
>>> request.form['form.buttons.continue'] = u'Continue'
>>> wizard = Wizard(None, request)
>>> html = wizard()
>>> 'wizard-step-two' in html
True

提交第二步

填写缺失的值

>>> request.form['two.widgets.beer'] = u'Boont Amber'

第二步工作方式类似

>>> request.form['two.widgets.name'] = u'David'
>>> wizard = Wizard(None, request)
>>> html = wizard()
>>> 'three' in html, 'Address' in html, 'City' in html, 'State' in html, 'Finish' in html
(True, True, True, True, True)

第三步:击败巨龙

现在让我们点击完成按钮。我们希望这会打印出第二步的值,归功于我们为该步骤实现的“应用”方法。

记住,在我们的向导中,我们实现了 finish 来打印接收到的数据。这里是终结技

>>> request.form['form.buttons.finish'] = u'Finish'
>>> wizard = Wizard(None, request)
>>> html = wizard()
'Name from step 2: David'
>>> messages = _decodeCookieValue(request.__annotations__.pop('statusmessages'))
>>> [(m.message, m.type) for m in messages]
[(u'Information submitted successfully.', u'info')]

示例

有关此库在使用的示例,请参阅 collective.megaphone 软件包。

AutoWizard

AutoWizard 从 plone.autoform 字段集创建步骤(包括 plone.supermodel xml 模式中定义的步骤)。

首先,我们定义我们的模式

>>> from plone.supermodel.interfaces import FIELDSETS_KEY
>>> from plone.supermodel.model import Fieldset
>>> from zope.interface import Interface, taggedValue
>>> class IMySchema(Interface):
...     age = schema.Int(title=u"Age")
...     name = schema.Int(title=u"Name")
...     taggedValue(FIELDSETS_KEY, [
...         Fieldset('one', label=u"One from fieldset", fields=['age']),
...         Fieldset('two', fields=['name']),
...         ])

然后创建 AutoWizard 类

>>> from collective.z3cform.wizard import autowizard
>>> class AutoWizard(autowizard.AutoWizard):
...     label = u"Automatically silly wizard."
...     schema = IMySchema

现在我们可以渲染表单

>>> request = TestRequest()
>>> wizard = AutoWizard(None, request)
>>> print wizard()
<...
<div class="form" id="wizard-step-form-one">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="form-one" enctype="multipart/form-data">
      <h2>One from fieldset</h2>
      <p class="discreet"></p>
      <div class="field">
        <label for="form-one-widgets-age">
          <span>Age</span>
        </label>...
        <span class="fieldRequired"
              title="Required">
          (Required)
        </span>
        <div class="widget">
          <input id="form-one-widgets-age" name="form.one.widgets.age"
                 class="text-widget required int-field" value=""
                 type="text" />
        </div>
      </div>
  <div class="formControls wizard-buttons">
      <input id="form-buttons-continue"
             name="form.buttons.continue"
             class="submit-widget button-field" value="Continue"
             type="submit" />
  </div>
  </form>
</div>

否则它的工作方式与标准向导完全相同。

动态向导支持

在某些情况下,根据用户对向导早期步骤的答案,后续步骤将显示或不显示给用户。

>>> from zope import schema
>>> from z3c.form import field, form
>>> from collective.z3cform.wizard import wizard
>>> from plone.z3cform.fieldsets import group
>>> from Products.statusmessages.interfaces import IStatusMessage
>>> from Products.statusmessages.adapter import _decodeCookieValue

我们定义字段。

>>> choiceField = schema.Choice(
...   __name__ = 'choice',
...   title=u'Choice',
...   values=(u'first', u'second'),
...   default=u'first'
...   )
>>> firstField = schema.TextLine(
...   __name__ = 'first',
...   title=u'First',
...   required=False,
...   missing_value=u'',
...   )
>>> secondField = schema.Bool(
...   __name__ = 'second',
...   title=u'Second',
...   required=False,
...   )

然后定义向导步骤。

>>> class FirstStep(wizard.Step):
...     label = u'First'
...     prefix = 'one'
...     fields = field.Fields(firstField)
...
...     def load(self, context):
...         data = self.getContent()
...         data.setdefault('first', u'initial first')
>>> class SecondStep(wizard.Step):
...     label = u'Second'
...     prefix = 'two'
...     fields = field.Fields(secondField)
...
...     def load(self, context):
...         data = self.getContent()
...         data['second'] = True
>>> class ChoiceStep(wizard.Step):
...     label = u'Choice'
...     prefix = 'choice'
...     fields = field.Fields(choiceField)
>>> class SecondChoiceStep(wizard.Step):
...     label = u'Second Choice'
...     prefix = 'second_choice'
...     fields = field.Fields(choiceField)

现在我们可以定义我们的动态向导。向导的后续步骤取决于在初始 ChoiceStepSecondChoiceStep 中提交的值。

steps 是一个计算属性,而不是硬编码的序列。

该类还实现了 showFinish 方法,用于控制显示(或不显示)完成按钮。

>>> class DynamicWizard(wizard.Wizard):
...     label = u"My dynamic wizard"
...
...     @property
...     def choice(self):
...         choice_data = self.session.get('choice', {})
...         choice = choice_data.get('choice', None)
...         if 'choice.widgets.choice' in self.request.form:
...             choice = unicode(self.request.form['choice.widgets.choice'][0])
...         return choice
...
...     @property
...     def second_choice(self):
...         choice_data = self.session.get('second_choice', {})
...         choice = choice_data.get('choice', None)
...         if 'second_choice.widgets.choice' in self.request.form:
...             choice = unicode(self.request.form['second_choice.widgets.choice'][0])
...         return choice
...
...     @property
...     def steps(self):
...         if self.choice == u'second':
...             if not self.second_choice:
...                 return [ChoiceStep, SecondChoiceStep, FirstStep]
...             elif self.second_choice == u'second':
...                 return [ChoiceStep, SecondChoiceStep, SecondStep]
...             else:
...                 return [ChoiceStep, SecondChoiceStep, FirstStep]
...         else:
...             return [ChoiceStep, FirstStep]
...
...     def showFinish(self):
...         return (self.choice == u'first' or self.second_choice) and self.allStepsFinished

渲染表单

现在让我们第一次渲染表单

>>> request = TestRequest()
>>> wizard = DynamicWizard(None, request)
>>> wizard.update()
>>> wizard.currentIndex
0
>>> print wizard.render()
<ul class="wizard-steps">
    <li class="wizard-step-link selected">
            1. Choice
    </li>
    <li class="wizard-step-link">
        <a href=".?step:int=1">
            2. First
        </a>
    </li>
</ul>
<div class="form" id="wizard-step-choice">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="choice" enctype="multipart/form-data">
      <h2>Choice</h2>
      <p class="discreet"></p>
      <div class="field">
        <label for="choice-widgets-choice">
          <span>Choice</span>
        </label>...
        <span class="fieldRequired"
              title="Required">
          (Required)
        </span>
        <div class="widget">
          <select id="choice-widgets-choice"
            name="choice.widgets.choice:list"
            class="select-widget required choice-field" size="1">
            <option id="choice-widgets-choice-0" value="first"
                    selected="selected">first</option>
            <option id="choice-widgets-choice-1" value="second">second</option>
          </select>
          <input name="choice.widgets.choice-empty-marker"
                 type="hidden" value="1" />
        </div>
      </div>
  <div class="formControls wizard-buttons">
      <input id="form-buttons-continue"
             name="form.buttons.continue"
             class="submit-widget button-field" value="Continue"
             type="submit" />
      <input id="form-buttons-clear"
             name="form.buttons.clear"
             class="submit-widget button-field" value="Clear"
             type="submit" />
  </div>
  </form>
</div>

成功提交第一个选择

>>> request.form = {
...     'form.buttons.continue': u'Continue',
...     'choice.widgets.choice': [u'first']
... }
>>> wizard = DynamicWizard(None, request)
>>> wizard.update()
>>> wizard.currentIndex
1
>>> print wizard.render()
<ul class="wizard-steps">
    <li class="wizard-step-link">
        <a href=".?step:int=0">
            1. Choice
        </a>
    </li>
    <li class="wizard-step-link selected">
            2. First
    </li>
</ul>
<div class="form" id="wizard-step-one">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="one" enctype="multipart/form-data">
      <h2>First</h2>
      <p class="discreet"></p>
                      <div class="field">
                        <label for="one-widgets-first">
                          <span>First</span>
                        </label>
                        <div class="widget">
    <input id="one-widgets-first" name="one.widgets.first"
           class="text-widget textline-field"
           value="initial first" type="text" />
                        </div>
                      </div>
    <div class="formControls wizard-buttons">
<input id="form-buttons-finish" name="form.buttons.finish"
       class="submit-widget button-field" value="Finish"
       type="submit" />
<input id="form-buttons-back" name="form.buttons.back"
       class="submit-widget button-field" value="Back"
       type="submit" />
<input id="form-buttons-clear" name="form.buttons.clear"
       class="submit-widget button-field" value="Clear"
       type="submit" />
    </div>
  </form>
</div>

后退

>>> del request.form['form.buttons.continue']
>>> request.form['form.buttons.back'] = u'Back'
>>> wizard = DynamicWizard(None, request)
>>> wizard.update()
>>> wizard.currentIndex
0
>>> print wizard.render()
<ul class="wizard-steps">
    <li class="wizard-step-link selected">
            1. Choice
    </li>
    <li class="wizard-step-link">
        <a href=".?step:int=1">
            2. First
        </a>
    </li>
</ul>
<div class="form" id="wizard-step-choice">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="choice" enctype="multipart/form-data">
      <h2>Choice</h2>
      <p class="discreet"></p>
                      <div class="field">
                        <label for="choice-widgets-choice">
                          <span>Choice</span>
                        </label>
                        <span class="fieldRequired"
    title="Required">
                          (Required)
                        </span>
                        <div class="widget">
<select id="choice-widgets-choice"
        name="choice.widgets.choice:list"
        class="select-widget required choice-field" size="1">
<option id="choice-widgets-choice-0" value="first"
        selected="selected">first</option>
<option id="choice-widgets-choice-1" value="second">second</option>
</select>
<input name="choice.widgets.choice-empty-marker"
       type="hidden" value="1" />
                        </div>
                      </div>
    <div class="formControls wizard-buttons">
<input id="form-buttons-continue"
       name="form.buttons.continue"
       class="submit-widget button-field" value="Continue"
       type="submit" />
<input id="form-buttons-finish" name="form.buttons.finish"
       class="submit-widget button-field" value="Finish"
       type="submit" />
<input id="form-buttons-clear" name="form.buttons.clear"
       class="submit-widget button-field" value="Clear"
       type="submit" />
    </div>
  </form>
</div>

选择向导的另一个分支

>>> request.form = {
...     'form.buttons.continue': u'Continue',
...     'choice.widgets.choice': [u'second']
... }
>>> wizard = DynamicWizard(None, request)
>>> wizard.update()
>>> wizard.currentIndex
1
>>> print wizard.render()
<ul class="wizard-steps">
    <li class="wizard-step-link">
        <a href=".?step:int=0">
            1. Choice
        </a>
    </li>
    <li class="wizard-step-link selected">
            2. Second Choice
    </li>
    <li class="wizard-step-link">
        <a href=".?step:int=2">
            3. First
        </a>
    </li>
</ul>
<div class="form" id="wizard-step-second_choice">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="second_choice" enctype="multipart/form-data">
      <h2>Second Choice</h2>
      <p class="discreet"></p>
                      <div class="field">
                        <label
    for="second_choice-widgets-choice">
                          <span>Choice</span>
                        </label>
                        <span class="fieldRequired"
    title="Required">
                          (Required)
                        </span>
                        <div class="widget">
<select id="second_choice-widgets-choice"
        name="second_choice.widgets.choice:list"
        class="select-widget required choice-field" size="1">
<option id="second_choice-widgets-choice-0" value="first"
        selected="selected">first</option>
<option id="second_choice-widgets-choice-1" value="second">second</option>
</select>
<input name="second_choice.widgets.choice-empty-marker"
       type="hidden" value="1" />
                        </div>
                      </div>
    <div class="formControls wizard-buttons">
<input id="form-buttons-continue"
       name="form.buttons.continue"
       class="submit-widget button-field" value="Continue"
       type="submit" />
<input id="form-buttons-back" name="form.buttons.back"
       class="submit-widget button-field" value="Back"
       type="submit" />
<input id="form-buttons-clear" name="form.buttons.clear"
       class="submit-widget button-field" value="Clear"
       type="submit" />
    </div>
  </form>
</div>

再次选择

>>> request.form = {
...     'form.buttons.continue': u'Continue',
...     'second_choice.widgets.choice': [u'second']
... }
>>> wizard = DynamicWizard(None, request)
>>> wizard.update()
>>> wizard.currentIndex
2

初始值实际上是显示的。

>>> print wizard.render()
<ul class="wizard-steps">
    <li class="wizard-step-link">
        <a href=".?step:int=0">
            1. Choice
        </a>
    </li>
    <li class="wizard-step-link">
        <a href=".?step:int=1">
            2. Second Choice
        </a>
    </li>
    <li class="wizard-step-link selected">
            3. Second
    </li>
</ul>
<div class="form" id="wizard-step-two">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="two" enctype="multipart/form-data">
      <h2>Second</h2>
      <p class="discreet"></p>
                      <div class="field">
                        <label for="two-widgets-second">
                          <span>Second</span>
                        </label>
                        <div class="widget">
<span class="option">
  <label for="two-widgets-second-0">
    <input id="two-widgets-second-0"
           name="two.widgets.second"
           class="radio-widget bool-field" value="true"
           checked="checked" type="radio" />
    <span class="label">yes</span>
  </label>
</span>
<span class="option">
  <label for="two-widgets-second-1">
    <input id="two-widgets-second-1"
           name="two.widgets.second"
           class="radio-widget bool-field" value="false"
           type="radio" />
    <span class="label">no</span>
  </label>
</span>
<input name="two.widgets.second-empty-marker" type="hidden"
       value="1" />
                        </div>
                      </div>
    <div class="formControls wizard-buttons">
<input id="form-buttons-finish" name="form.buttons.finish"
       class="submit-widget button-field" value="Finish"
       type="submit" />
<input id="form-buttons-back" name="form.buttons.back"
       class="submit-widget button-field" value="Back"
       type="submit" />
<input id="form-buttons-clear" name="form.buttons.clear"
       class="submit-widget button-field" value="Clear"
       type="submit" />
    </div>
  </form>
</div>

清除向导

>>> request.form = {
...     'form.buttons.clear': u'Clear',
...     'second_choice.widgets.choice': [u'second']
... }
>>> wizard = DynamicWizard(None, request)
>>> wizard.update()
>>> wizard.currentIndex
0
>>> print wizard.render()
<ul class="wizard-steps">
    <li class="wizard-step-link selected">
            1. Choice
    </li>
    <li class="wizard-step-link">
            2. First
    </li>
</ul>
<div class="form" id="wizard-step-choice">
  <form action="http://127.0.0.1" method="post"
        class="rowlike enableUnloadProtection kssattr-formname-127.0.0.1"
        id="choice" enctype="multipart/form-data">
      <h2>Choice</h2>
      <p class="discreet"></p>
                      <div class="field">
                        <label for="choice-widgets-choice">
                          <span>Choice</span>
                        </label>
                        <span class="fieldRequired"
    title="Required">
                          (Required)
                        </span>
                        <div class="widget">
<select id="choice-widgets-choice"
        name="choice.widgets.choice:list"
        class="select-widget required choice-field" size="1">
<option id="choice-widgets-choice-0" value="first"
        selected="selected">first</option>
<option id="choice-widgets-choice-1" value="second">second</option>
</select>
<input name="choice.widgets.choice-empty-marker"
       type="hidden" value="1" />
                        </div>
                      </div>
    <div class="formControls wizard-buttons">
<input id="form-buttons-continue"
       name="form.buttons.continue"
       class="submit-widget button-field" value="Continue"
       type="submit" />
    </div>
  </form>
</div>

项目详情


下载文件

下载适用于您平台的应用程序。如果您不确定要选择哪个,请了解更多关于 安装软件包 的信息。

源分布

collective.z3cform.wizard-1.4.8.zip (54.3 kB 查看散列)

上传于 源代码

支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面