=========== RadioWidget =========== The RadioWidget renders a radio input type field e.g. >>> from zope.interface.verify import verifyClass >>> from z3c.form import interfaces >>> from z3c.form.browser import radio The RadioWidget is a widget: >>> verifyClass(interfaces.IWidget, radio.RadioWidget) True The widget can render a input field only by adapting a request: >>> from z3c.form.testing import TestRequest >>> request = TestRequest() >>> widget = radio.RadioWidget(request) Set a name and id for the widget: >>> widget.id = 'widget-id' >>> widget.name = 'widget.name' Such a field provides IWidget: >>> interfaces.IWidget.providedBy(widget) True We also need to register the template for at least the widget and request: >>> import os.path >>> import zope.interface >>> from zope.publisher.interfaces.browser import IDefaultBrowserLayer >>> from zope.pagetemplate.interfaces import IPageTemplate >>> import z3c.form.browser >>> import z3c.form.widget >>> template = os.path.join(os.path.dirname(z3c.form.browser.__file__), ... 'radio_input.pt') >>> factory = z3c.form.widget.WidgetTemplateFactory(template) >>> zope.component.provideAdapter(factory, ... (zope.interface.Interface, IDefaultBrowserLayer, None, None, None), ... IPageTemplate, name='input') >>> template_single = os.path.join( ... os.path.dirname(z3c.form.browser.__file__), ... 'radio_input_single.pt') >>> zope.component.provideAdapter( ... z3c.form.widget.WidgetTemplateFactory(template_single), ... (zope.interface.Interface, IDefaultBrowserLayer, None, None, None), ... IPageTemplate, name='input_single') If we render the widget we only get the empty marker: >>> print(widget.render()) Let's provide some values for this widget. We can do this by defining a source providing ITerms. This source uses descriminators wich will fit for our setup. >>> import zope.schema.interfaces >>> import z3c.form.term >>> from zc.sourcefactory.basic import BasicSourceFactory >>> class YesNoSourceFactory(BasicSourceFactory): ... def getValues(self): ... return ['yes', 'no'] >>> class MyTerms(z3c.form.term.ChoiceTermsSource): ... def __init__(self, context, request, form, field, widget): ... self.terms = YesNoSourceFactory() >>> zope.component.provideAdapter(z3c.form.term.BoolTerms, ... adapts=(zope.interface.Interface, ... interfaces.IFormLayer, zope.interface.Interface, ... zope.interface.Interface, interfaces.IRadioWidget)) Now let's try if we get widget values: >>> widget.update() >>> print(widget.render()) If we set the value for the widget to ``yes``, we can se that the radio field get rendered with a checked flag: >>> widget.value = 'true' >>> widget.update() >>> print(widget.render()) We can also render the input elements for each value separately: >>> print(widget.renderForValue('true')) >>> print(widget.renderForValue('false')) Check HIDDEN_MODE: >>> template = os.path.join(os.path.dirname(z3c.form.browser.__file__), ... 'radio_hidden.pt') >>> factory = z3c.form.widget.WidgetTemplateFactory(template) >>> zope.component.provideAdapter(factory, ... (zope.interface.Interface, IDefaultBrowserLayer, None, None, None), ... IPageTemplate, name='hidden') >>> template = os.path.join(os.path.dirname(z3c.form.browser.__file__), ... 'radio_hidden_single.pt') >>> factory = z3c.form.widget.WidgetTemplateFactory(template) >>> zope.component.provideAdapter(factory, ... (zope.interface.Interface, IDefaultBrowserLayer, None, None, None), ... IPageTemplate, name='hidden_single') >>> widget.value = ['true'] >>> widget.mode = interfaces.HIDDEN_MODE >>> print(widget.render()) And independently: >>> print(widget.renderForValue('true')) The unchecked values do not need a hidden field, hence they are empty: >>> print(widget.renderForValue('false')) Check DISPLAY_MODE: >>> template = os.path.join(os.path.dirname(z3c.form.browser.__file__), ... 'radio_display.pt') >>> factory = z3c.form.widget.WidgetTemplateFactory(template) >>> zope.component.provideAdapter(factory, ... (zope.interface.Interface, IDefaultBrowserLayer, None, None, None), ... IPageTemplate, name='display') >>> template = os.path.join(os.path.dirname(z3c.form.browser.__file__), ... 'radio_display_single.pt') >>> factory = z3c.form.widget.WidgetTemplateFactory(template) >>> zope.component.provideAdapter(factory, ... (zope.interface.Interface, IDefaultBrowserLayer, None, None, None), ... IPageTemplate, name='display_single') >>> widget.value = ['true'] >>> widget.mode = interfaces.DISPLAY_MODE >>> print(widget.render()) yes And independently: >>> print(widget.renderForValue('true')) yes Again, unchecked values are not displayed: >>> print(widget.renderForValue('false')) Make sure that we produce a proper label when we have no title for a term and the value (which is used as a backup label) contains non-ASCII characters: >>> from zope.schema.vocabulary import SimpleVocabulary >>> terms = SimpleVocabulary.fromValues([b'yes\012', b'no\243']) >>> widget.terms = terms >>> widget.update() >>> pprint(widget.items) [{'checked': False, 'id': 'widget-id-0', 'label': 'yes\n', 'name': 'widget.name', 'value': 'yes\n'}, {'checked': False, 'id': 'widget-id-1', 'label': 'no', 'name': 'widget.name', 'value': 'no...'}] Note: The "\234" character is interpreted differently in Pytohn 2 and 3 here. (This is mostly due to changes int he SimpleVocabulary code.) Term with non ascii __str__ --------------------------- Check if a term which __str__ returns non ascii string does not crash the update method >>> request = TestRequest() >>> widget = radio.RadioWidget(request) >>> widget.id = 'widget-id' >>> widget.name = 'widget.name' >>> template = os.path.join(os.path.dirname(z3c.form.browser.__file__), ... 'radio_input.pt') >>> factory = z3c.form.widget.WidgetTemplateFactory(template) >>> zope.component.provideAdapter(factory, ... (zope.interface.Interface, IDefaultBrowserLayer, None, None, None), ... IPageTemplate, name='input') >>> import zope.schema.interfaces >>> from zope.schema.vocabulary import SimpleVocabulary,SimpleTerm >>> import z3c.form.term >>> class ObjWithNonAscii__str__: ... def __str__(self): ... return 'héhé!' >>> class MyTerms(z3c.form.term.ChoiceTermsVocabulary): ... def __init__(self, context, request, form, field, widget): ... self.terms = SimpleVocabulary([ ... SimpleTerm(ObjWithNonAscii__str__(), 'one', 'One'), ... SimpleTerm(ObjWithNonAscii__str__(), 'two', 'Two'), ... ]) >>> zope.component.provideAdapter(MyTerms, ... adapts=(zope.interface.Interface, ... interfaces.IFormLayer, zope.interface.Interface, ... zope.interface.Interface, interfaces.IRadioWidget)) >>> widget.update() >>> print(widget.render())