额外的zope.formlib小部件
项目描述
z3c.widget更改
0.3.0 (2010-11-16)
添加法语翻译。
更新测试以使用 zope.formlib 4.0 和 zope.schema 3.6。
使用Python的 doctest 模块而不是已弃用的 zope.testing.doctest[unit]。
将doctests添加到 long_description 以在PyPI上可见。
2008/01/29 0.2.1
为匈牙利语和罗马尼亚语添加翻译
2007/09/21 0.2.0
功能:添加了日期选择小部件。
功能:添加了社会保障号小部件。
功能:添加了美国电话号码小部件。
2007/09/19 0.1.7
为英文添加了翻译,以便在某些浏览器中启用 i18n 功能
2007/09/19 0.1.6
添加 cheesehop 分类,并在那里注册
修复了拼写错误
2007/09/05 0.1.5
错误修复:在打开文件对话框中点击取消后,浏览按钮现在将被启用
在上传开始之前不要将进度条设置为 100%
错误修复:如果没有设置限制,则不会上传文件
2007/09/05 0.1.4
处理上传过程中的文件大小。如果一个或多个文件的大小超过传递的大小,则在上传工作文件完成后,每个文件都将被忽略,但将在进度条下方列出。
显示最大允许的文件大小(如果包含在配置文件中)
2007/09/03 0.1.3
错误修复:过多的引号。
2007/09/03 0.1.2
使用传递的配置 URL 而不是硬编码的 flashuploadvars.xml
2007/08/06 0.1.1
flashupload:为 upload.swf 提供更好的可定制性。清理 Flash 内容的文件夹结构。
2007/06/14 0.1.0:
z3c.widget.image:为 es 添加了翻译
更新到最新的 bootstrap.py 版本
自动完成小部件
自动完成小部件是普通选择小部件的替代品。
>>> from z3c.widget.autocomplete.widget import AutoCompleteWidget
让我们创建一个词汇表。
>>> from zope.schema.vocabulary import SimpleVocabulary >>> from zope.publisher.browser import TestRequest >>> from zope import schema, component, interface >>> items = ((u'value1',1,u'Title1'), ... (u'value2',2,u'Title2'), ... (u'value3',3,u'Title3')) >>> terms = map(lambda i: SimpleVocabulary.createTerm(*i),items) >>> voc = SimpleVocabulary(terms) >>> [term.title for term in voc] [u'Title1', u'Title2', u'Title3'] >>> field = schema.Choice(__name__='foo', ... missing_value=None, ... vocabulary=voc) >>> request = TestRequest() >>> widget = AutoCompleteWidget(field, request) >>> widget <z3c.widget.autocomplete.widget.AutoCompleteWidget object at ...> >>> print widget() <input class="textType" id="field.foo" name="field.foo" type="text" value="" /> <div id="field.foo.target" class="autoComplete"></div> <script type="text/javascript"> new Ajax.Autocompleter('field.foo','field.foo.target', 'http://127.0.0.1/++widget++field.foo/suggestions' ,options={ paramName: 'value' }); </script>
让我们添加一些输入。请注意,输入必须与词汇表术语的标题匹配。
>>> request.form['field.foo']=u'Title1' >>> widget.getInputValue() u'value1'
如果没有匹配的标题,将引发 ConversionError。
>>> request.form['field.foo']=u'Unknown' >>> widget.getInputValue() Traceback (most recent call last): ... ConversionError: ('Invalid value', u'Unknown')
此外,表单值是具有给定值的术语的标题。
>>> widget._toFormValue('value1') u'Title1'>>> suggestions = widget.getSuggestions('Title') >>> [title for title in suggestions] [u'Title1', u'Title2', u'Title3'] >>> suggestions = widget.getSuggestions('Title1') >>> [title for title in suggestions] [u'Title1'] >>> suggestions = widget.getSuggestions('ABC') >>> [title for title in suggestions] [] >>> suggestions = widget.getSuggestions('title') >>> [title for title in suggestions] [u'Title1', u'Title2', u'Title3']
自动完成小部件演示
此演示包提供了一个简单的内容类,它使用 z3c 自动完成小部件。
>>> from zope.testbrowser.testing import Browser >>> browser = Browser() >>> browser.handleErrors = False >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw') >>> browser.open('https://127.0.0.1/@@contents.html')
可以通过点击添加菜单中的“自动完成小部件演示”链接来添加它。并给它一个名字。
>>> link = browser.getLink('Autocomplete Widget Demo') >>> link.click() >>> nameCtrl = browser.getControl(name='new_value') >>> nameCtrl.value = 'mydemo' >>> applyCtrl = browser.getControl('Apply') >>> applyCtrl.click() >>> link = browser.getLink('mydemo') >>> link.click() >>> browser.url 'https://127.0.0.1/mydemo/@@edit.html'
让我们通过直接访问来测试小部件的渲染。
>>> browser.open('https://127.0.0.1/mydemo/@@edit.html/++widget++country') >>> print browser.contents <input class="textType" ... </script>
建议由其自己的视图提供。
>>> browser.open('https://127.0.0.1/mydemo/@@edit.html/++widget++country/suggestions') >>> print browser.contents>>> browser.open('https://127.0.0.1/++lang++en/mydemo/@@edit.html/++widget++country/suggestions?value=a') >>> print browser.contents <BLANKLINE> <ul> <li>Algeria</li> <li>Andorra</li> <li>Antigua and Barbuda</li> <li>Afghanistan</li> <li>Anguilla</li> <li>Armenia</li> <li>Albania</li> <li>Angola</li> <li>Antarctica</li> <li>American Samoa</li> <li>Argentina</li> <li>Australia</li> <li>Austria</li> <li>Aruba</li> <li>Azerbaijan</li> </ul> <BLANKLINE> <BLANKLINE>
建议被翻译。
>>> browser.open('https://127.0.0.1/++lang++de/mydemo/@@edit.html/++widget++country/suggestions?value=a') >>> print browser.contents <BLANKLINE> <ul> <li>Amerikanische Jungferninseln</li> <li>Amerikanisch-Ozeanien</li> <li>Algerien</li> <li>Andorra</li> <li>Antigua und Barbuda</li> <li>Afghanistan</li> <li>Anguilla</li> <li>Armenien</li> <li>Albanien</li> <li>Angola</li> <li>Antarktis</li> <li>Amerikanisch-Samoa</li> <li>Argentinien</li> <li>Australien</li> <li>Aruba</li> <li>Aserbaidschan</li> </ul> <BLANKLINE> <BLANKLINE>
国家选择小部件
此包提供了选择国家的控件。下拉类型被注册为 Country 架构的默认值。
在翻译后对选项进行排序是件麻烦事。
在我们开始之前,我们必须做一些小小的设置
>>> import zope.component >>> import zope.schema >>> import zope.app.form.browser >>> from z3c.widget.country.widget import CountryInputDropdown >>> from z3c.widget.country import ICountry >>> from z3c.i18n.iso import territoryVocabularyFactory >>> from zope.publisher.interfaces.browser import IBrowserRequest
首先,我们必须创建一个字段和一个请求
>>> from z3c.widget.country import Country>>> countryFld = Country( ... __name__='country', ... title=u'Country', ... description=u'Select a Country')>>> from zope.publisher.browser import TestRequest >>> request = TestRequest()
现在我们可以初始化小部件。
>>> class Content(object): ... country = None >>> content = Content() >>> boundCountry = countryFld.bind(content)>>> widget = CountryInputDropdown(boundCountry, ... territoryVocabularyFactory(None), request)
让我们确保所有字段都有正确的值
>>> widget.name 'field.country'>>> widget.label u'Country'>>> widget.hint u'Select a Country'>>> widget.visible True
让我们看看小部件是如何渲染的
>>> print widget() <div> <div class="value"> <select id="field.country" name="field.country" size="1" > <option value="AF">Afghanistan</option> <option value="AL">Albania</option> <option value="DZ">Algeria</option> ... <option value="HU">Hungary</option> <option value="IS">Iceland</option> <option value="IN">India</option> ... <option value="ZM">Zambia</option> <option value="ZW">Zimbabwe</option> </select> ...
#让我们看看德语翻译:#z3c.i18n 注册所需!!! # # >>> request = TestRequest(HTTP_ACCEPT_LANGUAGE=’de’) # # >>> widget = CountryInputDropdown(boundCountry, # … territoryVocabularyFactory(None), request) # # >>> print widget() # <div> # <div class=”value”> # <select id=”field.country” name=”field.country” size=”1” > # <option value=”AF”>阿富汗斯坦</option> # <option value=”AL”>阿尔巴尼亚</option> # <option value=”DZ”>阿尔及利亚</option> # … # <option value=”HU”>匈牙利</option> # <option value=”IS”>冰岛</option> # <option value=”IN”>印度</option> # … # <option value=”ZM”>赞比亚</option> # <option value=”ZW”>津巴布韦</option> # </select> # …
日期选择小部件
“DateSelectWidget”小部件提供了三个选择框,分别表示日期、月份和年份。
首先,我们必须创建一个字段和一个请求。请注意,我们可以在该小部件中设置年份范围
>>> import datetime >>> from z3c.schema.dateselect import DateSelect >>> from z3c.widget.dateselect.browser import DateSelectWidget>>> field = DateSelect( ... title=u'Birthday', ... description=u'Somebodys birthday', ... yearRange=range(1930, 2007), ... required=True) >>> field.__name__ = 'field'>>> from zope.publisher.browser import TestRequest >>> request = TestRequest()
现在我们可以初始化小部件。
>>> widget = DateSelectWidget(field, request)
让我们确保所有字段都有正确的值
>>> widget.name 'field.field'>>> widget.label u'Birthday'>>> widget.hint u'Somebodys birthday'>>> widget.visible True>>> widget.required True
构造函数还应该创建了 3 个小部件
>>> widget.widgets['year'] <z3c.widget.dateselect.browser.DropdownWidget object at ...> >>> widget.widgets['month'] <z3c.widget.dateselect.browser.DropdownWidget object at ...> >>> widget.widgets['day'] <z3c.widget.dateselect.browser.DropdownWidget object at ...>
让我们也测试一下年份范围
>>> '1929' in widget.widgets['year'].vocabulary.by_token.keys() False >>> '1930' in widget.widgets['year'].vocabulary.by_token.keys() True >>> '2006' in widget.widgets['year'].vocabulary.by_token.keys() True >>> '2007' in widget.widgets['year'].vocabulary.by_token.keys() False
测试另一个年份范围
>>> field2 = DateSelect( ... title=u'Another Birthday', ... yearRange=range(2000, 2010)) >>> field2.__name__ = 'field' >>> widget2 = DateSelectWidget(field2, request)>>> '1930' in widget2.widgets['year'].vocabulary.by_token.keys() False >>> '2000' in widget2.widgets['year'].vocabulary.by_token.keys() True >>> '2009' in widget2.widgets['year'].vocabulary.by_token.keys() True >>> '2010' in widget2.widgets['year'].vocabulary.by_token.keys() False
setRenderedValue(value) 方法
第一个方法是 setRenderedValue()。根据值的类型,小部件有两个用途。如果值是自定义评分系统,它将信息发送到自定义、最小和最大小部件
>>> widget = DateSelectWidget(field, request) >>> year = 2000 >>> month = 12 >>> day = 31 >>> data = datetime.date(year, month, day) >>> widget.setRenderedValue(data)>>> 'value="2000"' in widget() True >>> 'value="12"' in widget() True >>> 'value="31"' in widget() True
setPrefix(prefix) 方法
前缀确定小部件及其所有子小部件的名称。
>>> widget.name 'field.field' >>> widget.widgets['year'].name 'field.field.year' >>> widget.widgets['month'].name 'field.field.month' >>> widget.widgets['day'].name 'field.field.day'>>> widget.setPrefix('test.')>>> widget.name 'test.field' >>> widget.widgets['year'].name 'test.field.year' >>> widget.widgets['month'].name 'test.field.month' >>> widget.widgets['day'].name 'test.field.day'
如果前缀不以点结尾,则添加一个点
>>> widget.setPrefix('test')>>> widget.name 'test.field' >>> widget.widgets['year'].name 'test.field.year' >>> widget.widgets['month'].name 'test.field.month' >>> widget.widgets['day'].name 'test.field.day'
getInputValue() 方法
此方法返回一个日期对象
>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '2', ... 'field.field.day': '24'})>>> widget = DateSelectWidget(field, request)>>> value = widget.getInputValue() >>> value.year 2006 >>> value.month 2 >>> value.day 24
如果一组值无法生成有效的日期对象,则会引发一个值错误
>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '2', ... 'field.field.day': '29'})>>> widget = DateSelectWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('field', u'Birthday', u'day is out of range for month')>>> widget._error.__class__ <class 'zope.formlib.interfaces.WidgetInputError'>
applyChanges(content) 方法
此方法将新日期应用于传入的内容。但是,它必须足够智能,以检测值是否真正发生了变化。
>>> class Content(object): ... field = None >>> content = Content()>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '2', ... 'field.field.day': '24'})>>> widget = DateSelectWidget(field, request) >>> widget.applyChanges(content) True >>> content.field datetime.date(2006, 2, 24)>>> widget.applyChanges(content) False
hasInput() 方法
此方法检查任何输入,但不对其进行验证。
>>> request = TestRequest() >>> widget = DateSelectWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.year': '2006'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.month': '2'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.day': '24'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '2', ... 'field.field.day': '24'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasInput() True
hasValidInput() 方法
除了检查任何输入外,此方法还检查输入是否有效
>>> request = TestRequest() >>> widget = DateSelectWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.year': '2006'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.month': '2'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.day': '24'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '2', ... 'field.field.day': '24'}) >>> widget = DateSelectWidget(field, request) >>> widget.hasValidInput() True
error() 方法
让我们测试一些不良数据并检查错误处理。
日期字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '2', ... 'field.field.day': '99'}) >>> widget = DateSelectWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... ConversionError: (u'Invalid value', InvalidValue("token '99' not found in vocabulary")) >>> print widget.error() <span class="error">Invalid value</span>
月份字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '0', ... 'field.field.day': '31'}) >>> widget = DateSelectWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... ConversionError: (u'Invalid value', InvalidValue("token '0' not found in vocabulary")) >>> print widget.error() <span class="error">Invalid value</span>
年份字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.year': '1900', ... 'field.field.month': '1', ... 'field.field.day': '31'}) >>> widget = DateSelectWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... ConversionError: (u'Invalid value', InvalidValue("token '1900' not found in vocabulary")) >>> print widget.error() <span class="error">Invalid value</span>
单个输入是正确的,但没有创建一个有效的日期。
>>> request = TestRequest(form={ ... 'field.field.year': '1980', ... 'field.field.month': '2', ... 'field.field.day': '31'}) >>> widget = DateSelectWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('field', u'Birthday', u'day is out of range for month')>>> print widget.error() <span class="error">day is out of range for month</span>
没有发生错误
>>> request = TestRequest(form={ ... 'field.field.year': '1980', ... 'field.field.month': '1', ... 'field.field.day': '31'}) >>> widget = DateSelectWidget(field, request) >>> widget.getInputValue() datetime.date(1980, 1, 31) >>> widget.error() ''
__call__() 方法
此方法使用子部件渲染小部件。让我们看看输出
>>> request = TestRequest(form={ ... 'field.field.year': '2006', ... 'field.field.month': '2', ... 'field.field.day': '24'}) >>> widget = DateSelectWidget(field, request) >>> print widget() <select id="field.field.day" name="field.field.day" size="1" > <option value="1">1</option> ... <option value="23">23</option> <option selected="selected" value="24">24</option> <option value="25">25</option> ... <option value="31">31</option> </select><input name="field.field.day-empty-marker" type="hidden" value="1" /> <select id="field.field.month" name="field.field.month" size="1" > <option value="1">1</option> <option selected="selected" value="2">2</option> <option value="3">3</option> ... <option value="12">12</option> </select><input name="field.field.month-empty-marker" type="hidden" value="1" /> <select id="field.field.year" name="field.field.year" size="1" > <option value="1930">1930</option> ... <option value="2005">2005</option> <option selected="selected" value="2006">2006</option> </select><input name="field.field.year-empty-marker" type="hidden" value="1" /> <BLANKLINE>
下拉日期小部件
>>> from z3c.widget.dropdowndatewidget.widget import DropDownDateWidget>>> from zope.publisher.browser import TestRequest >>> request = TestRequest()
小部件用于字段。
>>> from zope.schema import Date >>> dateField = Date(__name__='foo', title=u'Foo')>>> widget = DropDownDateWidget(dateField, request)>>> widget.name 'field.foo' >>> widget.label u'Foo' >>> widget.hasInput() False
我们需要提供一些输入。
>>> request.form['field.foo.day'] = '1' >>> widget.hasInput() False >>> request.form['field.foo.month'] = '6' >>> widget.hasInput() False >>> request.form['field.foo.year'] = '1963' >>> widget.hasInput() True
读取值。
>>> widget.getInputValue() datetime.date(1963, 6, 1)
让我们渲染小部件。
>>> print widget() <div class="dropDownDateWidget"><select class="dayField" id="field.foo.day" name="field.foo.day">...</select> <select class="monthField" id="field.foo.month" name="field.foo.month">...</select> <select class="yearField" id="field.foo.year" name="field.foo.year">...</select> </div>
如果我们设置一个值。
>>> from datetime import date >>> widget.setRenderedValue(date(1977, 4, 3)) >>> print widget() <div class="dropDownDateWidget"><select ...<option selected="selected" value="03">... <select ...<option selected="selected" value="04">... <select ...<option selected="selected" value="1977">... ...
FLASH上传小部件
flashupload vars页面配置了flash前端
>>> from z3c.widget.flashupload import upload >>> from zope.publisher.browser import TestRequest >>> from zope.app.pagetemplate import ViewPageTemplateFile >>> from zope.app.pagetemplate.simpleviewclass import SimpleViewClass >>> request = TestRequest() >>> context = object() >>> viewClass = SimpleViewClass( ... 'flashuploadvars.pt', bases=(upload.FlashUploadVars,)) >>> view = viewClass(context, request) >>> print view() <?xml version="1.0" ?> <var> <var name="file_progress">File Progress</var> <var name="overall_progress">Overall Progress</var> <var name="error">Error on uploading files</var> <var name="uploadcomplete">all files uploaded</var> <var name="uploadpartial">files uploaded</var> <var name="notuploaded">files were not uploaded because they're too big</var> <var name="maxfilesize">maximum file size is</var> </var>>>> view.allowedFileTypes = ('.jpg', '.gif') >>> print view() <?xml version="1.0" ?> <var> ... <var name="allowedFileType">.jpg</var> <var name="allowedFileType">.gif</var> </var>
图像小部件
此图像小部件应作为图像字段的自定义小部件使用。与zope3中的默认小部件相比,如果没有明确选择“删除”复选框,它不会删除字段中的数据。
添加图像
>>> import zope.schema >>> from zope.publisher.browser import TestRequest >>> from zope import interface >>> from zope.schema.fieldproperty import FieldProperty >>> from zope.app.file.interfaces import IImage >>> from z3c.widget.image.widget import ImageWidget >>> from zope.app.file.image import Image
创建一个具有图像字段的文档类型。
>>> class ITestObject(interface.Interface): ... image = zope.schema.Object( ... title=u'Image', ... schema=IImage) >>> class TestObject(object): ... interface.implements(ITestObject) ... image = FieldProperty(ITestObject['image'])>>> obj = TestObject()>>> field = ITestObject['image'].bind(obj)
发送不带任何图像信息的请求。空字段不应该被更改...
>>> request = TestRequest(form={'field.image' : u''}) >>> widget = ImageWidget(field, request) >>> widget._getFormInput() is None True
向字段发送一些图像信息。图像信息应作为图像对象存储在字段中
>>> request = TestRequest(form={'field.image' : u'PNG123Test'}) >>> widget = ImageWidget(field, request) >>> widget._getFormInput() <zope.app.file.image.Image object at ...>
现在我们再次保存字段,但不带任何新的图像数据。旧的图像信息不应丢失
>>> obj.image = Image(u'PNG123Test') >>> request = TestRequest(form={'field.image' : u''}) >>> widget = ImageWidget(field, request) >>> widget._getFormInput() is obj.image True
现在我们想要删除图像。表单输入现在应该是None。
>>> request = TestRequest(form={'field.image' : u'', ... 'field.image.delete': u'true'}) >>> widget = ImageWidget(field, request) >>> widget._getFormInput() is None True>>> print widget() <div class="z3cImageWidget"> <input type="file" name="field.image" id="field.image" /><br/> <input type="checkbox" name="field.image.delete" value="true" />delete image </div>
小部件命名空间
小部件命名空间提供了一种遍历表单库小部件的方法。
>>> from z3c.widget.namespace.namespace import WidgetHandler
让我们定义一个表单来测试此行为。
>>> from zope.formlib import form >>> from zope import interface, schema >>> class IMyContent(interface.Interface): ... title = schema.TextLine(title=u'Title') >>> class MyContent(object): ... interface.implements(IMyContent) ... title=None >>> content = MyContent() >>> from zope.publisher.browser import TestRequest >>> request = TestRequest() >>> class MyForm(form.EditForm): ... form_fields = form.Fields(IMyContent) >>> view = MyForm(content,request) >>> handler = WidgetHandler(view,request) >>> handler.traverse('title',None) <zope.formlib.textwidgets.TextWidget object at ...>
可选下拉小部件
可选下拉小部件模拟了常见的桌面组合框小部件,它还可以接收自定义条目。
在我们开始之前,我们必须做一些小小的设置
>>> import zope.component >>> import zope.schema >>> import zope.app.form.browser >>> from zope.publisher.interfaces.browser import IBrowserRequest>>> zope.component.provideAdapter( ... zope.app.form.browser.TextWidget, ... (zope.schema.interfaces.ITextLine, IBrowserRequest), ... zope.app.form.interfaces.IInputWidget)
首先,我们必须创建一个字段和一个请求
>>> from z3c.schema.optchoice import OptionalChoice>>> optchoice = OptionalChoice( ... __name__='occupation', ... title=u'Occupation', ... description=u'The Occupation', ... values=(u'Programmer', u'Designer', u'Project Manager'), ... value_type=zope.schema.TextLine())>>> from zope.publisher.browser import TestRequest >>> request = TestRequest()
现在我们可以初始化小部件。
>>> class Content(object): ... occupation = None >>> content = Content() >>> boundOptChoice = optchoice.bind(content)>>> from z3c.widget.optdropdown import OptionalDropdownWidget >>> widget = OptionalDropdownWidget(boundOptChoice, request)
让我们确保所有字段都有正确的值
>>> widget.name 'field.occupation'>>> widget.label u'Occupation'>>> widget.hint u'The Occupation'>>> widget.visible True>>> widget.required True
构造函数还应创建了2个小部件
>>> widget.customWidget <zope.formlib.textwidgets.TextWidget object at ...> >>> widget.dropdownWidget <zope.formlib.itemswidgets.DropdownWidget object at ...>
setRenderedValue(value) 方法
第一个方法是setRenderedValue()。根据值的类型,小部件有两个用途。如果值是自定义值,它将信息发送到自定义小部件
>>> print widget.customWidget() <... value="" /> >>> 'selected=""' in widget.dropdownWidget() False>>> widget.setRenderedValue(u'Scientist')>>> print widget.customWidget() <... value="Scientist" /> >>> 'selected=""' in widget.dropdownWidget() False
在重置小部件并传入词汇表中的其中一个选项后,值应在下拉列表中显示
>>> widget.setRenderedValue(u'Designer')>>> print widget.customWidget() <... value="" /> >>> print widget.dropdownWidget() <div> ... <option selected="selected" value="Designer">Designer</option> ... </div>
setPrefix(prefix) 方法
前缀决定了小部件和子小部件的名称。
>>> widget.name 'field.occupation' >>> widget.dropdownWidget.name 'field.occupation.occupation' >>> widget.customWidget.name 'field.occupation.custom'>>> widget.setPrefix('test.')>>> widget.name 'test.occupation' >>> widget.dropdownWidget.name 'test.occupation.occupation' >>> widget.customWidget.name 'test.occupation.custom'
getInputValue() 方法
此方法根据输入返回一个值;假定数据是有效的。在我们的情况下,这意味着如果我们输入了一个自定义值,它将被返回
>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher'})>>> widget = OptionalDropdownWidget(boundOptChoice, request)>>> widget.getInputValue() u'Teacher'
另一方面,如果我们从词汇表中选择了选项,它应该被返回
>>> request = TestRequest(form={ ... 'field.occupation.occupation': u'Designer'})>>> widget = OptionalDropdownWidget(boundOptChoice, request)>>> widget.getInputValue() u'Designer'
applyChanges(content) 方法
此方法将新值应用于传入的内容。但是,它必须足够智能,以检测值是否真正发生了变化。
>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher'})>>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.applyChanges(content) True >>> content.occupation u'Teacher'>>> widget.applyChanges(content) False>>> request = TestRequest(form={ ... 'field.occupation.occupation': u'Designer'})>>> widget = OptionalDropdownWidget(boundOptChoice, request)>>> widget.applyChanges(content) True >>> content.occupation u'Designer'>>> widget.applyChanges(content) False
hasInput() 方法
此方法检查任何输入,但不进行验证。在我们的情况下,这意味着已经选择了一个选项或输入了自定义值。
>>> request = TestRequest() >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher\nBad Stuff'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasInput() True>>> request = TestRequest(form={ ... 'field.occupation.occupation': u'Waitress'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasInput() True
hasValidInput() 方法
除了检查任何输入外,此方法还检查输入是否有效
>>> request = TestRequest() >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.occupation.occupation': u'Waitress'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.occupation.occupation': u'Designer'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasValidInput() True>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher\nBad Stuff'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.hasValidInput() True
error() 方法
再次,我们有两种情况。如果下拉列表中发生错误,将报告错误
>>> from zope.app.form.interfaces import IWidgetInputError >>> from zope.app.form.browser.exception import WidgetInputErrorView >>> from zope.app.form.browser.interfaces import IWidgetInputErrorView>>> zope.component.provideAdapter( ... WidgetInputErrorView, ... (IWidgetInputError, IBrowserRequest), IWidgetInputErrorView)>>> request = TestRequest(form={ ... 'field.occupation.occupation': u'Designer'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.getInputValue() u'Designer' >>> widget.error() ''>>> request = TestRequest(form={ ... 'field.occupation.occupation': u'Waitress'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request)>>> widget.getInputValue() Traceback (most recent call last): ... ConversionError: (u'Invalid value', InvalidValue("token u'Waitress' not found in vocabulary")) >>> widget.error() u'<span class="error">Invalid value</span>'
否则将报告自定义小部件的错误
>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.getInputValue() u'Teacher' >>> widget.error() ''>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher\nBad Stuff'}) >>> widget = OptionalDropdownWidget(boundOptChoice, request)>>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('custom', u'', ConstraintNotSatisfied(u'Teacher\nBad Stuff')) >>> widget.error() u'<span class="error">Constraint not satisfied</span>'
__call__() 方法
此方法使用子小部件渲染小部件。它简单地将两个小部件的输出添加在一起,在它们之间放置连接符
>>> request = TestRequest(form={ ... 'field.occupation.custom': u'Teacher'})>>> widget = OptionalDropdownWidget(boundOptChoice, request) >>> widget.connector u'<br />\n'>>> print widget() <div> <div class="value"> <select id="field.occupation.occupation" name="field.occupation.occupation" size="1" > <option selected="selected" value="">(nothing selected)</option> <option value="Programmer">Programmer</option> <option value="Designer">Designer</option> <option value="Project Manager">Project Manager</option> </select> </div> <input name="field.occupation.occupation-empty-marker" type="hidden" value="1" /> </div><br /> <input class="textType" id="field.occupation.custom" name="field.occupation.custom" size="20" type="text" value="Teacher" />
序列表小部件
此包提供了一个序列小部件,就像zope.app.form.browser.sequencewidget。主要区别在于它将子对象的字段水平放置在表格中。这意味着类似收据项目表单的工作变得非常容易。
还有一个小部件(SequenceTableJSWidget),它使用javascript在浏览器中执行添加/删除项目。诀窍是在HTML中嵌入一个不可见的空行模板,每次需要新行时都添加它。
- JS的缺点
验证仅在将整个表单提交到服务器时进行。
提交表单和使用浏览器后退按钮不起作用。
警告!
子对象必须具有子部件。如果子对象基于zope.schema.Object,则通常如此。
待办事项
测试。有些已经有了,有些是从z.a.form.browser复制的,需要修复。
SSN小部件
社会保险号码部件可以用作文本行字段的自定义部件,强制执行特定的布局。
首先,我们必须创建一个字段和一个请求
>>> import datetime >>> import zope.schema>>> field = zope.schema.TextLine( ... title=u'SSN', ... description=u'Social Security Number', ... required=True) >>> field.__name__ = 'field'>>> from zope.publisher.browser import TestRequest >>> request = TestRequest()
现在我们可以初始化小部件。
>>> from z3c.widget.ssn.browser import SSNWidget >>> widget = SSNWidget(field, request)
让我们确保所有字段都有正确的值
>>> widget.name 'field.field'>>> widget.label u'SSN'>>> widget.hint u'Social Security Number'>>> widget.visible True>>> widget.required True
构造函数还应创建3个子部件
>>> widget.widgets['first'] <zope.formlib.textwidgets.TextWidget object at ...> >>> widget.widgets['second'] <zope.formlib.textwidgets.TextWidget object at ...> >>> widget.widgets['third'] <zope.formlib.textwidgets.TextWidget object at ...>
setRenderedValue(value) 方法
第一种方法是setRenderedValue()。根据值的类型,部件有两个用例
>>> widget = SSNWidget(field, request) >>> widget.setRenderedValue(u'123-45-6789') >>> print widget() <input class="textType" id="field.field.first" name="field.field.first" size="3" type="text" value="123" /> — <input class="textType" id="field.field.second" name="field.field.second" size="2" type="text" value="45" /> — <input class="textType" id="field.field.third" name="field.field.third" size="4" type="text" value="6789" />
setPrefix(prefix) 方法
前缀确定小部件及其所有子小部件的名称。
>>> widget.name 'field.field' >>> widget.widgets['first'].name 'field.field.first' >>> widget.widgets['second'].name 'field.field.second' >>> widget.widgets['third'].name 'field.field.third'>>> widget.setPrefix('test.')>>> widget.name 'test.field' >>> widget.widgets['first'].name 'test.field.first' >>> widget.widgets['second'].name 'test.field.second' >>> widget.widgets['third'].name 'test.field.third'
如果前缀不以点结尾,则添加一个点
>>> widget.setPrefix('test')>>> widget.name 'test.field' >>> widget.widgets['first'].name 'test.field.first' >>> widget.widgets['second'].name 'test.field.second' >>> widget.widgets['third'].name 'test.field.third'
getInputValue() 方法
此方法返回完整的SSN字符串
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45', ... 'field.field.third': '6789'})>>> widget = SSNWidget(field, request)>>> value = widget.getInputValue() >>> value u'123-45-6789'
如果一组值不产生有效的字符串,则会引发值错误
>>> request = TestRequest(form={ ... 'field.field.first': '1234', ... 'field.field.second': '56', ... 'field.field.third': '7890'})>>> widget = SSNWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('first', u'Frst three digits', ConstraintNotSatisfied(u'1234'))>>> widget._error.__class__ <class 'zope.formlib.interfaces.WidgetInputError'>
applyChanges(content) 方法
此方法将新的SSN应用于传递的内容。但是,它必须足够智能,能够检测值是否真的已更改。
>>> class Content(object): ... field = None >>> content = Content()>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45', ... 'field.field.third': '6789'})>>> widget = SSNWidget(field, request) >>> widget.applyChanges(content) True >>> content.field u'123-45-6789'>>> widget.applyChanges(content) False
hasInput() 方法
此方法检查任何输入,但不对其进行验证。
>>> request = TestRequest() >>> widget = SSNWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123'}) >>> widget = SSNWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.second': '45'}) >>> widget = SSNWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45', ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> widget.hasInput() True
hasValidInput() 方法
除了检查任何输入外,此方法还检查输入是否有效
>>> request = TestRequest() >>> widget = SSNWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123'}) >>> widget = SSNWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.second': '45'}) >>> widget = SSNWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45', ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> widget.hasValidInput() True
error() 方法
让我们测试一些不良数据并检查错误处理。
第三个字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45', ... 'field.field.third': '678'}) >>> widget = SSNWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('third', u'Third four digits', ConstraintNotSatisfied(u'678')) >>> print widget.error() <span class="error">Constraint not satisfied</span>
第二个字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '4-', ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('second', u'Second two digits', ConstraintNotSatisfied(u'4-')) >>> print widget.error() <span class="error">Constraint not satisfied</span>
第一个字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.first': 'xxx', ... 'field.field.second': '45', ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('first', u'Frst three digits', ConstraintNotSatisfied(u'xxx')) >>> print widget.error() <span class="error">Constraint not satisfied</span>
没有发生错误
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45', ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> widget.getInputValue() u'123-45-6789' >>> widget.error() ''
__call__() 方法
此方法使用子部件渲染小部件。让我们看看输出
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45', ... 'field.field.third': '6789'}) >>> widget = SSNWidget(field, request) >>> print widget() <input class="textType" id="field.field.first" name="field.field.first" size="3" type="text" value="123" /> — <input class="textType" id="field.field.second" name="field.field.second" size="2" type="text" value="45" /> — <input class="textType" id="field.field.third" name="field.field.third" size="4" type="text" value="6789" />
HTML-Editor小部件 TinyMCE
此包通过使用优秀的TinyMCE编辑器(见:http://tinymce.moxiecode.com/)提供HTML内容的WYSIWYG-Editor-Widget。
美国电话小部件
美国电话号码部件可以用作文本行字段的自定义部件,强制执行特定的布局。
首先,我们必须创建一个字段和一个请求
>>> import datetime >>> import zope.schema>>> field = zope.schema.TextLine( ... title=u'Phone', ... description=u'Phone Number', ... required=True) >>> field.__name__ = 'field'>>> from zope.publisher.browser import TestRequest >>> request = TestRequest()
现在我们可以初始化小部件。
>>> from z3c.widget.usphone.browser import PhoneWidget >>> widget = PhoneWidget(field, request)
让我们确保所有字段都有正确的值
>>> widget.name 'field.field'>>> widget.label u'Phone'>>> widget.hint u'Phone Number'>>> widget.visible True>>> widget.required True
构造函数还应创建3个子部件
>>> widget.widgets['first'] <zope.formlib.textwidgets.TextWidget object at ...> >>> widget.widgets['second'] <zope.formlib.textwidgets.TextWidget object at ...> >>> widget.widgets['third'] <zope.formlib.textwidgets.TextWidget object at ...>
setRenderedValue(value) 方法
第一种方法是setRenderedValue()。根据值的类型,部件有两个用例
>>> widget = PhoneWidget(field, request) >>> widget.setRenderedValue(u'123-456-7890') >>> print widget() (<input class="textType" id="field.field.first" name="field.field.first" size="3" type="text" value="123" />) <input class="textType" id="field.field.second" name="field.field.second" size="3" type="text" value="456" /> — <input class="textType" id="field.field.third" name="field.field.third" size="4" type="text" value="7890" />
setPrefix(prefix) 方法
前缀确定小部件及其所有子小部件的名称。
>>> widget.name 'field.field' >>> widget.widgets['first'].name 'field.field.first' >>> widget.widgets['second'].name 'field.field.second' >>> widget.widgets['third'].name 'field.field.third'>>> widget.setPrefix('test.')>>> widget.name 'test.field' >>> widget.widgets['first'].name 'test.field.first' >>> widget.widgets['second'].name 'test.field.second' >>> widget.widgets['third'].name 'test.field.third'
如果前缀不以点结尾,则添加一个点
>>> widget.setPrefix('test')>>> widget.name 'test.field' >>> widget.widgets['first'].name 'test.field.first' >>> widget.widgets['second'].name 'test.field.second' >>> widget.widgets['third'].name 'test.field.third'
getInputValue() 方法
此方法返回完整的电话字符串
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '456', ... 'field.field.third': '7890'})>>> widget = PhoneWidget(field, request)>>> value = widget.getInputValue() >>> value u'123-456-7890'
如果一组值不产生有效的字符串,则会引发值错误
>>> request = TestRequest(form={ ... 'field.field.first': '1234', ... 'field.field.second': '56', ... 'field.field.third': '7890'})>>> widget = PhoneWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('first', u'Area Code', ConstraintNotSatisfied(u'1234'))>>> widget._error.__class__ <class 'zope.formlib.interfaces.WidgetInputError'>
applyChanges(content) 方法
此方法将新的电话号码应用于传递的内容。但是,它必须足够智能,能够检测值是否真的已更改。
>>> class Content(object): ... field = None >>> content = Content()>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '456', ... 'field.field.third': '7890'})>>> widget = PhoneWidget(field, request) >>> widget.applyChanges(content) True >>> content.field u'123-456-7890'>>> widget.applyChanges(content) False
hasInput() 方法
此方法检查任何输入,但不对其进行验证。
>>> request = TestRequest() >>> widget = PhoneWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123'}) >>> widget = PhoneWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.second': '456'}) >>> widget = PhoneWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> widget.hasInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '456', ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> widget.hasInput() True
hasValidInput() 方法
除了检查任何输入外,此方法还检查输入是否有效
>>> request = TestRequest() >>> widget = PhoneWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123'}) >>> widget = PhoneWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.second': '456'}) >>> widget = PhoneWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> widget.hasValidInput() False>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '456', ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> widget.hasValidInput() True
error() 方法
让我们测试一些不良数据并检查错误处理。
第三个字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '456', ... 'field.field.third': '78901'}) >>> widget = PhoneWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('third', u'Four Digits', ConstraintNotSatisfied(u'78901'))>>> print widget.error() <span class="error">Constraint not satisfied</span>
第二个字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '45-', ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('second', u'Three Digits', ConstraintNotSatisfied(u'45-'))>>> print widget.error() <span class="error">Constraint not satisfied</span>
第一个字段包含无效值
>>> request = TestRequest(form={ ... 'field.field.first': 'xxx', ... 'field.field.second': '456', ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> widget.getInputValue() Traceback (most recent call last): ... WidgetInputError: ('first', u'Area Code', ConstraintNotSatisfied(u'xxx'))>>> print widget.error() <span class="error">Constraint not satisfied</span>
没有发生错误
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '456', ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> widget.getInputValue() u'123-456-7890' >>> widget.error() ''
__call__() 方法
此方法使用子部件渲染小部件。让我们看看输出
>>> request = TestRequest(form={ ... 'field.field.first': '123', ... 'field.field.second': '456', ... 'field.field.third': '7890'}) >>> widget = PhoneWidget(field, request) >>> print widget() (<input class="textType" id="field.field.first" name="field.field.first" size="3" type="text" value="123" />) <input class="textType" id="field.field.second" name="field.field.second" size="3" type="text" value="456" /> — <input class="textType" id="field.field.third" name="field.field.third" size="4" type="text" value="7890" />
项目详情
z3c.widget-0.3.0.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f5432f07ee9f28586eeea573a48a4af10a950efad8651de815bc043407f03f0d |
|
MD5 | e5936e943a9fb4f75ed45c51111a5790 |
|
BLAKE2b-256 | ff81fc884bb8c411579254401e626e517f1b456257cc58b8b27ebff8a58d2574 |