Package: z3c.widget
ContentsChanges for z3c.widget0.3.0 (2010-11-16)2008/01/29 0.2.12007/09/21 0.2.02007/09/19 0.1.72007/09/19 0.1.62007/09/05 0.1.52007/09/05 0.1.42007/09/03 0.1.32007/09/03 0.1.22007/08/06 0.1.12007/06/14 0.1.0:Autocomplete WidgetsAutoCompleteWidget DemoCountry selection WidgetsDate Selection WidgetsetRenderedValue(value)MethodsetPrefix(prefix)MethodgetInputValue()MethodapplyChanges(content)MethodhasInput()MethodhasValidInput()Methodhidden()Methoderror()Method__call__()MethodDropDownDateWidgetFLASH UPLOAD WIDGETThe Image WidgetAdding an ImageThe Widget NamespaceOptional Dropdown WidgetssetRenderedValue(value)MethodsetPrefix(prefix)MethodgetInputValue()MethodapplyChanges(content)MethodhasInput()MethodhasValidInput()Methodhidden() Methoderror() Method__call__() MethodSequenceTable WidgetWARNING!TODOSSN WidgetsetRenderedValue(value)MethodsetPrefix(prefix)MethodgetInputValue()MethodapplyChanges(content)MethodhasInput()MethodhasValidInput()Methodhidden()Methoderror()Method__call__()MethodHTML-Editor Widget TinyMCEUS Phone WidgetsetRenderedValue(value)MethodsetPrefix(prefix)MethodgetInputValue()MethodapplyChanges(content)MethodhasInput()MethodhasValidInput()Methodhidden()Methoderror()Method__call__()MethodChanges for z3c.widget0.3.0 (2010-11-16)Added translation for french.Updated tests to run withzope.formlib4.0 andzope.schema3.6.Using Python’sdoctestmodule instead of depreactedzope.testing.doctest[unit].Added doctests tolong_descriptionto be visible on PyPI.2008/01/29 0.2.1add translation for hungarian and romanian languages2007/09/21 0.2.0feature: Added a date-selection widget.feature: Added a social security number widget.feature: Added a US phone number widget.2007/09/19 0.1.7added translation for english to get i18n working in some browsers2007/09/19 0.1.6added cheesehop classification, registered therefixed typos2007/09/05 0.1.5bugfix: browse butten will now be enabled after cancel was clicked in
the open file dialogdo not set the progessbar to 100% before the upload was startedbugfix: files will not be uploaded if no limit was set2007/09/05 0.1.4dealing file size during upload. If one or more files are bigger than
the passed size each one of them will be ignored during upload but listed
below the progress bar after the upload of the working files is done.displaying the maximal allowed file size (if it’s contained in the config
file)2007/09/03 0.1.3bugfix: too much quoting.2007/09/03 0.1.2using passed config url instead of hard coded flashuploadvars.xml2007/08/06 0.1.1flashupload: better skinnability for upload.swf. cleanup folder
structure for flash stuff.2007/06/14 0.1.0:z3c.widget.image: added translations for esupdate to newest bootstrap.py versionAutocomplete WidgetsAutocomplete widgets are an alternative to normal select widgets.>>> from z3c.widget.autocomplete.widget import AutoCompleteWidgetLet us create a vocabulary.>>> 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>Let’s add some input. Note that the input must match the title of the
vocabulary term.>>> request.form['field.foo']=u'Title1'
>>> widget.getInputValue()
u'value1'If we have no matching title a ConversionError is raised.>>> request.form['field.foo']=u'Unknown'
>>> widget.getInputValue()
Traceback (most recent call last):
...
ConversionError: ('Invalid value', u'Unknown')Also the form value is the title of the term with the given value.>>> 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']AutoCompleteWidget DemoThis demo packe provides a simple content class which uses the
z3c autocomplete widget.>>> from zope.testbrowser.testing import Browser
>>> browser = Browser()
>>> browser.handleErrors = False
>>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
>>> browser.open('http://localhost/@@contents.html')It can be added by clicking on the “Autocomplete Widget Demo” link in the
add menu. And giving it a name.>>> 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
'http://localhost/mydemo/@@edit.html'Let us test the widget rendering by direct access.>>> browser.open('http://localhost/mydemo/@@edit.html/++widget++country')
>>> print browser.contents
<input class="textType" ...
</script>The suggestions are proveded by its own view.>>> browser.open('http://localhost/mydemo/@@edit.html/++widget++country/suggestions')
>>> print browser.contents>>> browser.open('http://localhost/++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>Suggestions are translated.>>> browser.open('http://localhost/++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 selection WidgetsThis package provides widgets to select a country.
The dropdown type is registered as a default for the Country schema.The pain was to sort the options after the translation.Before we can start, we have to do a little bit of setup:>>> 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 IBrowserRequestFirst we have to create a field and a request:>>> 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()Now we can initialize the widget.>>> class Content(object):
...     country = None
>>> content = Content()
>>> boundCountry = countryFld.bind(content)>>> widget = CountryInputDropdown(boundCountry,
...   territoryVocabularyFactory(None), request)Let’s make sure that all fields have the correct value:>>> widget.name
'field.country'>>> widget.label
u'Country'>>> widget.hint
u'Select a Country'>>> widget.visible
TrueLet’s see how the widget is rendered:>>> 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>
...#Let’s see the german translation:
#z3c.i18n registrations required!!!
#
#  >>> 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”>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>
#  …Date Selection WidgetTheDateSelectWidgetwidget provides three select boxes presenting the
day, month and year.First we have to create a field and a request. Note that we can set the
year range in this widget:>>> 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()Now we can initialize widget.>>> widget = DateSelectWidget(field, request)Let’s make sure that all fields have the correct value:>>> widget.name
'field.field'>>> widget.label
u'Birthday'>>> widget.hint
u'Somebodys birthday'>>> widget.visible
True>>> widget.required
TrueThe constructor should have also created 3 widgets:>>> 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 ...>let’s also test the year range:>>> '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()
FalseTest another year range:>>> 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()
FalsesetRenderedValue(value)MethodThe first method issetRenderedValue(). The widget has two use cases,
based on the type of value. If the value is a custom score system, it will
send the information to the custom, min and max widget:>>> 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()
TruesetPrefix(prefix)MethodThe prefix determines the name of the widget and all its sub-widgets.>>> 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'If the prefix does not end in a dot, one is added:>>> 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()MethodThis method returns a date object:>>> 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
24If a set of values does not produce a valid date object, a value error is
raised:>>> 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)MethodThis method applies the new date to the passed content. However, it
must be smart enough to detect whether the values really changed.>>> 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)
FalsehasInput()MethodThis method checks for any input, but does not validate it.>>> 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()
TruehasValidInput()MethodAdditionally to checking for any input, this method also checks whether the
input is valid:>>> 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()
Truehidden()MethodThis method is renders the output as hidden fields:>>> request = TestRequest(form={
...     'field.field.year': '2006',
...     'field.field.month': '2',
...     'field.field.day': '24'})
>>> widget = DateSelectWidget(field, request)
>>> print widget.hidden()
<input class="hiddenType" id="field.field.year" name="field.field.year"
       type="hidden" value="2006" />
<input class="hiddenType" id="field.field.month" name="field.field.month"
       type="hidden" value="2"  />
<input class="hiddenType" id="field.field.day" name="field.field.day"
       type="hidden" value="24"  />error()MethodLet’s test some bad data and check the error handling.The day field contains an invalid value:>>> 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>The month field contains an invalid value:>>> 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>The year field contains an invalid value:>>> 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>The single inputs were correct, but did not create a valid date.>>> 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>No error occurred:>>> 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__()MethodThis method renders the widget using the sub-widgets. Let’s see the output:>>> 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" />&nbsp;
<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" />&nbsp;
<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>DropDownDateWidget>>> from z3c.widget.dropdowndatewidget.widget import DropDownDateWidget>>> from zope.publisher.browser import TestRequest
>>> request = TestRequest()Widgets are use for fields.>>> 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()
FalseWe need to provide some input.>>> 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()
TrueRead the value.>>> widget.getInputValue()
datetime.date(1963, 6, 1)Let’s render the widget.>>> 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>And if we set a value.>>> 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 UPLOAD WIDGETthe flashupload vars page configures the flash frontend>>> 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>The Image Widgetthis image widget should be used as a custom_widget for image fields.
comparing to the default widget in zope3 it does not delete the
data in the field if the “delete” checkbox is not explicitly selected.Adding an Image>>> 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 Imagecreate a content type with an image field.>>> 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)Send the request without any image information. the empty field
should not be changed…>>> request = TestRequest(form={'field.image' : u''})
>>> widget = ImageWidget(field, request)
>>> widget._getFormInput() is None
TrueSend some Image information to the field. the image information
should be stored in the field as a Image Object>>> request = TestRequest(form={'field.image' : u'PNG123Test'})
>>> widget = ImageWidget(field, request)
>>> widget._getFormInput()
<zope.app.file.image.Image object at ...>Now we save the field again, but without any new image data.
the old image information should not be lost>>> obj.image = Image(u'PNG123Test')
>>> request = TestRequest(form={'field.image' : u''})
>>> widget = ImageWidget(field, request)
>>> widget._getFormInput() is obj.image
TrueNow we want to delete the image. the forminput should be None now.>>> 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>The Widget NamespaceThe widget namespace provides a way to traverse to the widgets of a
formlib form.>>> from z3c.widget.namespace.namespace import WidgetHandlerLet us define a form to test this behaviour.>>> 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 ...>Optional Dropdown WidgetsThe Optional Dropdown Widget simulates the common desktop widget of a combo
box, which can also receive a custom entry.Before we can start, we have to do a little bit of setup:>>> 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)First we have to create a field and a request:>>> 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()Now we can initialize widget.>>> class Content(object):
...     occupation = None
>>> content = Content()
>>> boundOptChoice = optchoice.bind(content)>>> from z3c.widget.optdropdown import OptionalDropdownWidget
>>> widget = OptionalDropdownWidget(boundOptChoice, request)Let’s make sure that all fields have the correct value:>>> widget.name
'field.occupation'>>> widget.label
u'Occupation'>>> widget.hint
u'The Occupation'>>> widget.visible
True>>> widget.required
TrueThe constructor should have also created 2 widgets:>>> widget.customWidget
<zope.formlib.textwidgets.TextWidget object at ...>
>>> widget.dropdownWidget
<zope.formlib.itemswidgets.DropdownWidget object at ...>setRenderedValue(value)MethodThe first method issetRenderedValue(). The widget has two use cases,
based on the type of value. If the value is a custom value, it will
send the information to the custom widget:>>> print widget.customWidget()
<... value="" />
>>> 'selected=""' in widget.dropdownWidget()
False>>> widget.setRenderedValue(u'Scientist')>>> print widget.customWidget()
<... value="Scientist" />
>>> 'selected=""' in widget.dropdownWidget()
FalseAfter resetting the widget passing in one of the choices in the
vocabulary, the value should be displayed in the dropdown:>>> widget.setRenderedValue(u'Designer')>>> print widget.customWidget()
<... value="" />
>>> print widget.dropdownWidget()
<div>
...
<option selected="selected" value="Designer">Designer</option>
...
</div>setPrefix(prefix)MethodThe prefix determines the name of the widget and the sub-widgets.>>> 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()MethodThis method returns a value based on the input; the data is assumed to
be valid. In our case that means, if we entered a custom value, it is
returned:>>> request = TestRequest(form={
...     'field.occupation.custom': u'Teacher'})>>> widget = OptionalDropdownWidget(boundOptChoice, request)>>> widget.getInputValue()
u'Teacher'On the other hand, if we selected a choice from the vocabulary, it should be
returned:>>> request = TestRequest(form={
...     'field.occupation.occupation': u'Designer'})>>> widget = OptionalDropdownWidget(boundOptChoice, request)>>> widget.getInputValue()
u'Designer'applyChanges(content)MethodThis method applies the new value to the passed content. However, it
must be smart enough to detect whether the values really changed.>>> 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)
FalsehasInput()MethodThis mehtod checks for any input, but does not validate it. In our case this
means that either a choice has been selected or the the custom value has been
entered.>>> 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()
TruehasValidInput()MethodAdditionally to checking for any input, this method also checks whether the
input is valid:>>> 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()
Truehidden() MethodThis method is implemented by simply concatenating the two widget’s hidden
output:>>> request = TestRequest()
>>> widget = OptionalDropdownWidget(boundOptChoice, request)
>>> widget.setRenderedValue(u'Designer')
>>> print widget.hidden()
<input class="hiddenType" id="field.occupation.occupation"
       name="field.occupation.occupation" type="hidden" value="Designer"  />
<input class="hiddenType" id="field.occupation.custom"
       name="field.occupation.custom" type="hidden" value=""  />>>> widget.setRenderedValue(u'Teacher')
>>> print widget.hidden()
<input class="hiddenType" id="field.occupation.occupation"
       name="field.occupation.occupation" type="hidden" value=""  />
<input class="hiddenType" id="field.occupation.custom"
       name="field.occupation.custom" type="hidden" value="Teacher"  />error() MethodAgain, we have our two cases. If an error occured in the dropdown, it is
reported:>>> 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>'Otherwise the custom widget’s errors are reported:>>> 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__() MethodThis method renders the widget using the sub-widgets. It simply adds the two
widgets’ output placing theconnectorbetween them:>>> 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" />SequenceTable WidgetThis package provides a Sequence Widget just as
zope.app.form.browser.sequencewidget.
The main difference is that it places the subobject’s fields horizontally in
a table. That means a kind of voucher-item forms are piece of cake to do.There is also a widget (SequenceTableJSWidget) which does the add/remove item
in the browser with javascript.
The trick is to embed an invisible template of an empty row in the HTML,
add that each time a new row is required.Drawbacks of JS:Validation is done ONLY when the complete form is submitted to the server.Submitting the form and using the Back button of the browser does not work.WARNING!The subobject MUST have subwidgets. That is usually the case if the subobject
is based on zope.schema.Object.TODOTests.
Some are there, some are copied from z.a.form.browser and need fix.SSN WidgetThe social security number widget can be used as a custom widget for text line
fields, enforcing a particular layout.First we have to create a field and a request:>>> 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()Now we can initialize widget.>>> from z3c.widget.ssn.browser import SSNWidget
>>> widget = SSNWidget(field, request)Let’s make sure that all fields have the correct value:>>> widget.name
'field.field'>>> widget.label
u'SSN'>>> widget.hint
u'Social Security Number'>>> widget.visible
True>>> widget.required
TrueThe constructor should have also created 3 sub-widgets:>>> 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)MethodThe first method issetRenderedValue(). The widget has two use cases,
based on the type of value:>>> 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"  />&nbsp;&mdash;&nbsp;
<input class="textType" id="field.field.second" name="field.field.second"
       size="2" type="text" value="45"  />&nbsp;&mdash;&nbsp;
<input class="textType" id="field.field.third" name="field.field.third"
       size="4" type="text" value="6789"  />setPrefix(prefix)MethodThe prefix determines the name of the widget and all its sub-widgets.>>> 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'If the prefix does not end in a dot, one is added:>>> 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()MethodThis method returns the full SSN string:>>> 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'If a set of values does not produce a valid string, a value error is
raised:>>> 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)MethodThis method applies the new SSN to the passed content. However, it
must be smart enough to detect whether the values really changed.>>> 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)
FalsehasInput()MethodThis method checks for any input, but does not validate it.>>> 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()
TruehasValidInput()MethodAdditionally to checking for any input, this method also checks whether the
input is valid:>>> 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()
Truehidden()MethodThis method is renders the output as hidden fields:>>> request = TestRequest(form={
...     'field.field.first': '123',
...     'field.field.second': '45',
...     'field.field.third': '6789'})
>>> widget = SSNWidget(field, request)
>>> print widget.hidden()
<input class="hiddenType" id="field.field.first" name="field.field.first"
       type="hidden" value="123" />
<input class="hiddenType" id="field.field.second" name="field.field.second"
       type="hidden" value="45"  />
<input class="hiddenType" id="field.field.third" name="field.field.third"
       type="hidden" value="6789"  />error()MethodLet’s test some bad data and check the error handling.The third field contains an invalid value:>>> 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>The second field contains an invalid value:>>> 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>The first field contains an invalid value:>>> 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>No error occurred:>>> 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__()MethodThis method renders the widget using the sub-widgets. Let’s see the output:>>> 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"  />&nbsp;&mdash;&nbsp;
<input class="textType" id="field.field.second" name="field.field.second"
       size="2" type="text" value="45"  />&nbsp;&mdash;&nbsp;
<input class="textType" id="field.field.third" name="field.field.third"
       size="4" type="text" value="6789"  />HTML-Editor Widget TinyMCEThis package provides a WYSIWYG-Editor-Widget for HTML-Content, by
using the greate TinyMCE editor (see:http://tinymce.moxiecode.com/).US Phone WidgetThe US phone number widget can be used as a custom widget for text line
fields, enforcing a particular layout.First we have to create a field and a request:>>> 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()Now we can initialize widget.>>> from z3c.widget.usphone.browser import PhoneWidget
>>> widget = PhoneWidget(field, request)Let’s make sure that all fields have the correct value:>>> widget.name
'field.field'>>> widget.label
u'Phone'>>> widget.hint
u'Phone Number'>>> widget.visible
True>>> widget.required
TrueThe constructor should have also created 3 sub-widgets:>>> 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)MethodThe first method issetRenderedValue(). The widget has two use cases,
based on the type of value:>>> 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"  />)&nbsp;
<input class="textType" id="field.field.second" name="field.field.second"
       size="3" type="text" value="456"  />&nbsp;&mdash;&nbsp;
<input class="textType" id="field.field.third" name="field.field.third"
       size="4" type="text" value="7890"  />setPrefix(prefix)MethodThe prefix determines the name of the widget and all its sub-widgets.>>> 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'If the prefix does not end in a dot, one is added:>>> 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()MethodThis method returns the full phone string:>>> 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'If a set of values does not produce a valid string, a value error is
raised:>>> 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)MethodThis method applies the new phone number to the passed content. However, it
must be smart enough to detect whether the values really changed.>>> 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)
FalsehasInput()MethodThis method checks for any input, but does not validate it.>>> 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()
TruehasValidInput()MethodAdditionally to checking for any input, this method also checks whether the
input is valid:>>> 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()
Truehidden()MethodThis method is renders the output as hidden fields:>>> request = TestRequest(form={
...     'field.field.first': '123',
...     'field.field.second': '456',
...     'field.field.third': '7890'})
>>> widget = PhoneWidget(field, request)
>>> print widget.hidden()
<input class="hiddenType" id="field.field.first" name="field.field.first"
       type="hidden" value="123" />
<input class="hiddenType" id="field.field.second" name="field.field.second"
       type="hidden" value="456"  />
<input class="hiddenType" id="field.field.third" name="field.field.third"
       type="hidden" value="7890"  />error()MethodLet’s test some bad data and check the error handling.The third field contains an invalid value:>>> 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>The second field contains an invalid value:>>> 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>The first field contains an invalid value:>>> 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>No error occurred:>>> 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__()MethodThis method renders the widget using the sub-widgets. Let’s see the output:>>> 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"  />)&nbsp;
<input class="textType" id="field.field.second" name="field.field.second"
       size="3" type="text" value="456"  />&nbsp;&mdash;&nbsp;
<input class="textType" id="field.field.third" name="field.field.third"
       size="4" type="text" value="7890"  />