Plone dict字段的z3c表单小部件

Plone dict字段的z3c表单小部件,plone,z3c.form,Plone,Z3c.form,我正在尝试创建一个自定义小部件,用于zope.schema.Dict字段。这些键将自动从用户列表中提取,值将是select vocab中的一个。我已经或多或少地完成了大部分工作,但我的问题是在保存表单时。我使用的是plone.app.registry.browser.controlpanel.RegistryEditForm视图,模式包含有问题的Dict字段。我得到以下错误: Traceback (innermost last): Module ZPublisher.Publish, lin

我正在尝试创建一个自定义小部件,用于zope.schema.Dict字段。这些键将自动从用户列表中提取,值将是select vocab中的一个。我已经或多或少地完成了大部分工作,但我的问题是在保存表单时。我使用的是plone.app.registry.browser.controlpanel.RegistryEditForm视图,模式包含有问题的Dict字段。我得到以下错误:

Traceback (innermost last):
  Module ZPublisher.Publish, line 60, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 46, in call_object
  Module plone.z3cform.layout, line 70, in __call__
  Module plone.z3cform.layout, line 54, in update
  Module plone.z3cform.fieldsets.extensible, line 59, in update
  Module plone.z3cform.patch, line 30, in GroupForm_update
  Module z3c.form.group, line 138, in update
  Module z3c.form.action, line 99, in execute
  Module z3c.form.button, line 315, in __call__
  Module z3c.form.button, line 170, in __call__
  Module plone.app.registry.browser.controlpanel, line 55, in handleSave
  Module z3c.form.group, line 92, in extractData
  Module z3c.form.form, line 145, in extractData
  Module z3c.form.field, line 301, in extract
  Module zope.component.hooks, line 104, in adapter_hook
  Module z3c.form.converter, line 79, in FieldWidgetDataConverter
  Module zope.component._api, line 120, in queryMultiAdapter
  Module zope.component.registry, line 238, in queryMultiAdapter
  Module zope.interface.adapter, line 532, in queryMultiAdapter
  Module z3c.form.converter, line 71, in __init__
TypeError: Field ``mypackage_dict`` of type ``Dict`` must provide ``IFromUnicode``.
我试图创建一个转换器,但我显然做错了什么

小部件代码:

class MyPackageWidget(Widget):
    implementsOnly(IMyPackageWidget)

    klass = u'mypackage-widget'
    input_template = ViewPageTemplateFile("input.pt")

    def render(self):
        if self.mode == INPUT_MODE:
            return self.input_template()

    def users(self):
        utility = getUtility(IMyPackageUtility)
        frequencies = utility.frequencies()
        for usr in plone.api.user.get_users():
            user_id = usr.getId()
            yield {'id': user_id,
                   'myvalue': frequencies.get(user_id),
                   'name': usr.getProperty('fullname') or user_id}

    def extract(self, default=NO_VALUE):
        field_key = self.name + '.'
        myvalues = {}
        for key in self.request.keys():
            if key.startswith(field_key):
                user_id = safe_unicode(key[len(field_key):])
                value = self.request.get(key)
                myvalues[user_id] = value
        return myvalues

    def options(self):
        for term in frequencies._terms:
            yield {'value': term.value,
                   'content': term.title}


@adapter(IDict, IFormLayer)
@implementer(IFieldWidget)
def MyPackageFieldWidget(field, request):
    """ IFieldWidget factory for MyPackageWidget
    """
    return FieldWidget(field, MyPackageWidget(request))


class MyPackageDataConverter(BaseDataConverter):
    """Convert between the context and the widget"""

    adapts(IDict, IMyPackageWidget)

    def toWidgetValue(self, value):
        return value

    def toFieldValue(self, value):
        return value
转换器实际上还没有做任何事情。我还不确定它需要做什么,但我在这些方法中添加了堆栈跟踪,只是从一开始就没有被命中。我确实验证了提取代码是否将数据格式化为合理的格式,并且应该满足我定义的字段

zcml:

如果我创建一个plone.directives.form.SchemaForm,那么返回的数据值['mypackage\u dict']看起来很好,我可以将其保存到注册表中。不过,如果我能理解它试图转换的内容,我希望能够使用controlpanel.RegistryEditForm类更自动地进行转换


Plone 4.2

我追踪到z3c.form.field(2.5.1)第301行,在那里它调用“interfaces.IDataConverter(widget)”,我在那里得到一个类型错误“无法适应”。该方法捕获异常并执行其他操作,但我认为它应该能够为这个小部件找到一个转换器。令人沮丧的是,它真的不需要转换器。原始变量验证得很好。
  <class class=".widgets.MyPackageWidget">
    <require
        permission="zope.Public"
        interface="my.package.interfaces.widget.IMyPackageWidget"
        />
  </class>

  <adapter
        factory=".widgets.MyPackageDataConverter"
        />

  <adapter
      factory=".widgets.MyPackageFieldWidget"
      provides="z3c.form.interfaces.IFieldWidget"
      for="zope.schema.interfaces.IDict
           zope.schema.interfaces.IField
           my.package.interfaces.widget.IWidgetsLayer"
      />

  <z3c:widgetTemplate
      mode="input"
      widget="my.package.interfaces.widget.IMyPackageWidget"
      layer="my.package.interfaces.widget.IWidgetsLayer"
      template="input.pt"
      />

</configure>
form.widget(member_frequencies=MyPackageFieldWidget)
mypackage_dict = schema.Dict(
    title=_(u"Member/subscription"),
    key_type=schema.TextLine(),
    value_type=schema.Choice(source=setting_options),
)