Словарь источник, функция не повторяется, с ловкостью в Plone 4.1
У меня есть пользовательский тип контента Dexterity, который описывается в файле colle.z3c.datagrid, следующим образом:
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-behaviour/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]
)
Внутри формы "Редактировать и добавить" поле "Выбор" работает правильно. Но когда я пытаюсь сохранить содержимое:
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
Почему это происходит?
2 ответа
Это происходит, когда поле не было связано или отсутствует контекст. Обычно проверка будет происходить с "связанным" полем (bound = field.bind(context)
) так что ваш контекстно-зависимый словарь может быть превращен в статический словарь для этого контекста. Это все еще будет функция (не вызывается с контекстом), когда этого не произошло.
Я недостаточно знаком с настройкой виджета сетки данных, чтобы точно определить, где это происходит, но кажется, что он генерирует виджеты на лету, и я подозреваю, что он не связывает поля для них правильно. Взгляни на DataGridField.getWidget
метод collective.z3cform.datagridfield.datagridfield
модуль и попытайтесь выяснить, что там происходит, с помощью отладчика и / или сообщите об ошибке авторам пакета.
Я решил проблему, предоставив свой собственный словарь в качестве Именованного словаря, следующим образом:
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")
и в моих схемах типа контента Dexterity:
class ILanguageRow(Interface):
# Interface that defines a datagrid row.
lang = schema.Choice(
title=_(u'Language'), required=True,
vocabulary=u"my.content.LanguagesVocabulary",
)
Таким образом, это работает.