1

我有一个自定义的敏捷内容类型,collective.z3c.datagridfield 按以下方式定义:

class ILanguageRow(Interface):
    # Interface that defines a datagrid row.
    lang = schema.Choice(
        title=_(u'Language'), required=True, 
        source=my_languages,
        default=u'en',
    )

(...)

这是返回词汇表的函数,如http://plone.org/products/dexterity/documentation/manual/schema-driven-forms/customising-form-b​​ehaviour /vocabularies

@grok.provider(IContextSourceBinder)
def languages(context):
    """
    Return a vocabulary of language codes and
    translated language names.
    """

    # z3c.form KSS inline validation hack
    if not ISiteRoot.providedBy(context):
        for item in getSite().aq_chain:
            if ISiteRoot.providedBy(item):
                context = item

    # retrieve the localized language names.
    request = getRequest()
    portal_state = getMultiAdapter((context, request), name=u'plone_portal_state')
    lang_items = portal_state.locale().displayNames.languages.items()

    # build the dictionary
    return SimpleVocabulary(
        [SimpleTerm(value=lcode, token=lcode, title=lname)\
          for lcode, lname in sorted(lang_items) if lcode in config.CV_LANGS]
    )

在 Edit and Add Form 中,Choice 字段可以正常工作。但是当我尝试保存内容时:

TypeError: argument of type 'function' is not iterable
2011-07-08 13:37:40 ERROR Zope.SiteErrorLog 1310125060.840.103138625259 http://localhost:8081/Plone/++add++my.content.types.curriculum
Traceback (innermost last):
  Module ZPublisher.Publish, line 126, 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 my.content.types.curriculum, line 356, 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 134, in update
  Module z3c.form.group, line 47, in update
  Module z3c.form.group, line 43, in updateWidgets
  Module z3c.form.field, line 275, in update
  Module z3c.form.browser.multi, line 61, in update
  Module z3c.form.browser.widget, line 70, in update
  Module z3c.form.widget, line 396, in update
  Module z3c.form.widget, line 88, in update
  Module z3c.form.widget, line 390, in set
  Module collective.z3cform.datagridfield.datagridfield, line 112, in updateWidgets
  Module collective.z3cform.datagridfield.datagridfield, line 90, in getWidget
  Module z3c.form.browser.widget, line 70, in update
  Module z3c.form.object, line 213, in update
  Module z3c.form.widget, line 88, in update
  Module collective.z3cform.datagridfield.datagridfield, line 216, in set
  Module z3c.form.object, line 229, in applyValue
  Module z3c.form.validator, line 67, in validate
  Module zope.schema._bootstrapfields, line 153, in validate
  Module zope.schema._field, line 325, in _validate
TypeError: argument of type 'function' is not iterable

为什么会这样?

4

2 回答 2

2

当字段尚未绑定或缺少上下文时,就会发生这种情况。通常验证将针对“绑定”字段 ( bound = field.bind(context)) 进行,以便您的上下文感知词汇可以转换为该上下文的静态词汇。当这没有发生时,它仍然是一个函数(不使用上下文调用)。

我对 datagrid 小部件设置不够熟悉,无法查明哪里出了问题,但它似乎即时生成小部件,我怀疑它没有正确绑定这些字段。查看模块的DataGridField.getWidget方法collective.z3cform.datagridfield.datagridfield并尝试使用调试器找出那里发生的事情和/或向包的作者提交错误。

于 2011-07-08T13:29:06.857 回答
2

我通过提供我的自定义词汇作为命名词汇解决了这个问题,以这种方式:

from Products.CMFCore.interfaces import ISiteRoot
from zope.component import getMultiAdapter
from zope.site.hooks import getSite
from zope.globalrequest import getRequest

from my.content import config

class LanguagesVocabulary(object):

    grok.implements(IVocabularyFactory)

    def __call__(self, context):
        # z3c.form KSS inline validation hack
        if not ISiteRoot.providedBy(context):
            for item in getSite().aq_chain:
                if ISiteRoot.providedBy(item):
                    context = item

        # retrieve the localized language names.
        request = getRequest()
        portal_state = getMultiAdapter((context, request), name=u'plone_portal_state')
        lang_items = portal_state.locale().displayNames.languages.items()

        # build the dictionary
        terms = [SimpleTerm(value=lcode, token=lcode, title=lname)\
          for lcode, lname in sorted(lang_items) if lcode in config.CV_LANGS]

        return SimpleVocabulary(terms)

grok.global_utility(LanguagesVocabulary, name=u"my.content.LanguagesVocabulary")

在我的敏捷内容类型模式中:

class ILanguageRow(Interface):
    # Interface that defines a datagrid row.
    lang = schema.Choice(
        title=_(u'Language'), required=True, 
        vocabulary=u"my.content.LanguagesVocabulary",
    )

这样就可以了。

于 2011-07-08T14:16:46.667 回答