I have an add-on configuration page/form generated by plone.app.registry.browser.controlpanel
Using these Docs:
http://plone.org/documentation/kb/how-to-create-a-plone-control-panel-with-plone.app.registry
https://pypi.python.org/pypi/plone.app.registry#control-panel-widget-settings
On this form, I have an integer field:
from zope import schema
from plone.app.registry.browser import controlpanel
class MyAddonSettings(Interface):
partnerId = schema.Int(title=u"Partner Id",
description=u"enter your Partner ID",
required=True,
default=54321)
class SettingsEditForm(controlpanel.RegistryEditForm):
schema = MyAddonSettings
label = u"My settings"
description = u""""""
def updateFields(self):
super(SettingsEditForm, self).updateFields()
def updateWidgets(self):
super(SettingsEditForm, self).updateWidgets()
class SettingsControlPanel(controlpanel.ControlPanelFormWrapper):
form = SettingsEditForm
When the form renders, I get the integer field auto-filled with '54,321' I don't want the comma.
How to I specify "Don't do that!"
So, I think I went pretty deep down the rabbit hole, but here is what I came up with.
1) The default widget for zope.schema.Int is the TextWidget
2) z3c.form.converter.IntegerDataConverter Adapts itself to zope.schema.interfaces.IInt and ITextWidget
3) the IntegerDataConverter calls upon the locale to 'format the integer' for you, giving you a nice pretty representation of an int - with commas.
My choice was to create a new widget 'IntWidget' and a new converter 'NoFormatIntegerDataConverter', adapt these. Then manually set the field in question to my new widget:
I'm sure there is a less 'rabbit hole' way to do this, but I found myself at the bottom, so I completed the journey. I'll let a zope guru follow up with the 'right' way to do it.
=========================
so we don't tie our new converter to everyone's TextWidget and break someone else's stuff
import zope.interface
import zope.component
import zope.schema.interfaces
import z3c.form.interfaces
from z3c.form.widget import FieldWidget
from z3c.form.browser.text import TextWidget
from z3c.form import converter
class IIntWidget(z3c.form.interfaces.ITextWidget):
"""Int Widget"""
class IntWidget(TextWidget):
zope.interface.implementsOnly(IIntWidget)
klass = u'int-widget'
value = u''
@zope.component.adapter(zope.schema.interfaces.IField,
z3c.form.interfaces.IFormLayer)
@zope.interface.implementer(z3c.form.interfaces.IFieldWidget)
def IntFieldWidget(field, request):
"""IFieldWidget factory for IntWidget."""
return FieldWidget(field, IntWidget(request))
zope.component.provideAdapter(IntFieldWidget)
class NoFormatIntegerDataConverter(converter.IntegerDataConverter):
""" data converter that ignores the formatter,
simply returns the unicode representation of the integer value
The base class for this calls upon the locale for a formatter.
This completely avoids calling the locale.
"""
zope.component.adapts(zope.schema.interfaces.IInt, IIntWidget)
def toWidgetValue(self, value):
if value is self.field.missing_value:
return u''
#go look at z3c.form.converter.IntegerDataConverter
#to see what it used to return here.
return unicode(value)
zope.component.provideAdapter(NoFormatIntegerDataConverter)
class SettingsEditForm(controlpanel.RegistryEditForm):
...
def updateFields(self):
super(SettingsEditForm, self).updateFields()
self.fields['partnerId'].widgetFactory = IntFieldWidget #<----- Here
...