Question

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!"

Was it helpful?

Solution

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.

=========================

create the new widget based on TextWidget

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)

Create the 'dumb' converter, and adapt it to our new widget 'IntWidget'

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)

Finally, update the field widget factory to use our new widget

class SettingsEditForm(controlpanel.RegistryEditForm):

    ...

    def updateFields(self):
        super(SettingsEditForm, self).updateFields()
        self.fields['partnerId'].widgetFactory = IntFieldWidget  #<----- Here

    ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top