My problem & fixing attempts
I have a Plone 4 site which I have used collective.examples.userdata on in order to register new custom fields on the registration form and ##personal-information page. One of my fields needs to be a selection list allowing the user to specify which team from the organisation they are in.
I have successfully got the selection list appearing on the registration form and ##personal-information forms, however I am falling flat when trying to figure out how to add it to the mysite.com/portal_memberdata page.
I have tried adding a field to this page with the following information:
Name: team
Type: selection
Value: getTeamValue
getTeamValue is a Python script that contains:
return ('(nothing selected)','Volunteers','Trustees',
'Quality, Education & Learning','Bereavement Support',
'Supportive Care Services','Hospice at Home',
'Day Services','Medical Team','Inpatient Unit'
,'HR','Support Services','Accounts & IT',
'Communications','Trading','Fundraising')
Now when I alter the drop down lists value and try to save the changes, (on ##personal-information) I get the following traceback:
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 zope.formlib.form, line 795, in __call__
Module five.formlib.formbase, line 50, in update
Module zope.formlib.form, line 776, in update
Module zope.formlib.form, line 620, in success
Module plone.app.users.browser.account, line 64, in handle_edit_action
Module zope.formlib.form, line 543, in applyChanges
Module zope.formlib.form, line 538, in applyData
Module zope.schema._bootstrapfields, line 227, in set
Module kcs.userdata.adapter, line 20, in set_team
Module Products.PlonePAS.tools.memberdata, line 261, in setMemberProperties
Module Products.PlonePAS.sheet, line 75, in setProperty
Module Products.PlonePAS.sheet, line 72, in validateProperty
PropertyValueError: Invalid value (Volunteers) for property 'team' of type lines
I have also tried setting the Value field to both lines and string, but both result in the same traceback, however the bottom line's lines word is replaced for string or selection etc.
Code used
These are the excerpts of code I use in my add-on to add the selection box to the user registration:
adapter.py
def get_team(self):
return self.context.getProperty('team','')
def set_team(self, value):
return self.context.setMemberProperties({'team': value})
team = property(get_team, set_team)
userdataschema.py
team = schema.Choice(
title=_(u'label_team', default=u'Select your team'),
description=_(u'help_team', default=u"Select your team from the list below"),
values = [
_(u'Volunteers'),
_(u'Trustees'),
_(u'Quality, Education & Learning'),
_(u'Bereavement Support'),
_(u'Supportive Care Services'),
_(u'Hospice at Home'),
_(u'Day Services'),
_(u'Medical Team'),
_(u'Inpatient Unit'),
_(u'HR'),
_(u'Support Services'),
_(u'Accounts & IT'),
_(u'Communications'),
_(u'Trading'),
_(u'Fundraising')
],
required=True,
)
memberdata_properties.xml
<?xml version="1.0"?>
<object name="portal_memberdata" meta_type="Plone Memberdata Tool">
<property name="position" type="string"></property>
<property name="linkedin" type="string"></property>
<property name="team" type="choice"></property>
<property name="accept" type="boolean"></property>
</object>
propertiestool.xml
<?xml version="1.0"?>
<object name="portal_properties" meta_type="Plone Properties Tool">
<object name="site_properties" meta_type="Plone Property Sheet">
<property name="user_registration_fields" type="lines">
<element value="position" />
<element value="linkedin" />
<element value="team" />
<element value="accept" />
</property>
</object>
</object>
Let me know if I need to provide more information and any thoughts would be greatly appreciated.
Related
I'm having this issue while running tests only after I removed the <includeDependencies package="." /> directive from my configure.zcml file:
Error in test test_get_load_action (sc.embedder.tests.test_content.MultimediaTestCase)
Traceback (most recent call last):
File "/home/hvelarde/collective/buildout.python/parts/opt/lib/python2.7/unittest/case.py", line 329, in run
testMethod()
File "/home/hvelarde/collective/sc.embedder/src/sc/embedder/tests/test_content.py", line 135, in test_get_load_action
edit_form.update()
File "/home/hvelarde/.buildout/eggs/plone.dexterity-1.1.2-py2.7.egg/plone/dexterity/browser/edit.py", line 52, in update
super(DefaultEditForm, self).update()
File "/home/hvelarde/.buildout/eggs/plone.z3cform-0.7.8-py2.7.egg/plone/z3cform/fieldsets/extensible.py", line 59, in update
super(ExtensibleForm, self).update()
File "/home/hvelarde/.buildout/eggs/plone.z3cform-0.7.8-py2.7.egg/plone/z3cform/patch.py", line 30, in GroupForm_update
_original_GroupForm_update(self)
File "/home/hvelarde/.buildout/eggs/z3c.form-2.5.1-py2.7.egg/z3c/form/group.py", line 125, in update
self.updateWidgets()
File "/home/hvelarde/.buildout/eggs/z3c.form-2.5.1-py2.7.egg/z3c/form/form.py", line 129, in updateWidgets
(self, self.request, self.getContent()), interfaces.IWidgets)
File "/home/hvelarde/.buildout/eggs/zope.component-3.9.5-py2.7.egg/zope/component/_api.py", line 109, in getMultiAdapter
raise ComponentLookupError(objects, interface, name)
ComponentLookupError: ((<Products.Five.metaclass.EditForm object at 0x7f5262a3f490>, <HTTPRequest, URL=http://nohost>, <Embedder at /plone/test-folder/multimedia>), <InterfaceClass z3c.form.interfaces.IWidgets>, u'')
Same versions where working before; current configure.zcml now includes the following:
<include package="Products.CMFCore" file="permissions.zcml" />
<include package="plone.app.dexterity" />
<include package="plone.app.dexterity" file="meta.zcml" />
<include package="five.grok" />
According to the documentation this is a known issue due to a bad migration, but this can't the case.
I'm testing under Plone 4.2.6. Same code works and tests pass under Plone 4.3 as you can see in the CI builds.
Seems I was missing a package on the configure.zcml declaration; now it looks like this:
<include package="Products.CMFCore" file="permissions.zcml" />
<include package="plone.app.dexterity" />
<include package="plone.app.dexterity" file="meta.zcml" />
<include package="collective.dexteritytextindexer" />
and now is working: https://travis-ci.org/simplesconsultoria/sc.embedder/builds/126432050
I'm trying to implement a wizard that will update a form a then (if possible, send a signal to workflow to change status of an object, but that will be for later). I'm trying and trying, but I'm doing something wrong since I get stuck with this annoying error!
ValueError: No such external ID currently defined in the system: processos_uc.reformulate_generic_request_wizard
I've got these two files inside the "wizard" folder:
reformulate_wizard.py:
from openerp.osv import osv
from openerp.osv import fields
from openerp.tools.translate import _
class ref_generic_request(osv.osv_memory):
_name='ref.generic.request'
_columns = {
'reformulation_info': fields.text('Reformulation instructions', help='Instructions for the requestor justification the reformulation needs'),
}
def save_info(self, cr, uid, ids, context=None):
if 'active_id' in context:
info=self.browse(cr,uid,ids)[0].reformulation_info
self.pool.get('generic.request').write(cr,uid,context['active_id'],
{'reformulation_info' : reformulation_info})
return {
'type': 'ir.actions.act_window_close',
}
ref_generic_request()
reformulate_wizard.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_reformulate_generic_request_wizard" model="ir.ui.view">
<field name="name">reformulate_generic_request_wizard.form</field>
<field name="model">ref.generic.request</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Insert reformulation info" version="7.0">
<group colspan="4" >
<separator string="bla bla bla here" colspan="4"/>
<field name="reformulation_info" string="Reformulation info"/>
<newline/>
</group>
<separator string="" colspan="4" />
<group colspan="4" col="6">
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
<button icon="gtk-ok" name="save_info" string="Send to reformulation" type="object" />
</group>
</form>
</field>
</record>
<record id="action_reformulate_generic_request" model="ir.actions.act_window">
<field name="name">Reformulate Request</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ref.generic.request</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_reformulate_generic_request_wizard"/>
<field name="target">new</field>
</record>
<act_window id="action_reformulate_generic_request"
name="Reformulate Request"
res_model="generic.request"
view_mode="form"
target="new"
/>
</data>
</openerp>
And I didn't forget the __init__.py with the "import reformulate_wizard" in it.
I am calling the wizard from my xml view like this (and I guess that's where I'm getting the error):
<button name="%(reformulate_generic_request_wizard)d" string="Button that calls wizard" type="object" />
In my base folder I'm importing the wizard folder inside the __init__.py:
import parecer
import pedido_generico
import tracing
import wizard
And here is the content of my __openerp__.py (The error might be from the order I'm loading things):
{
'name': 'Processos UC',
'version': '0.1',
'category': 'Tools',
'description': """
OpenERP Module that implements UC's business processes.""",
'author': 'Filipe Castanheira',
'website': 'http://www.uc.pt',
'depends': ['base','web'],
'demo': [],
'test':[],
#'js': [
# 'static/js/custom.js',
#],
'css': [ 'static/css/uc_css.css' ],
'update_xml' : [
'data/action_server.xml',
'security/security.xml',
'security/processos_uc_domain_rules.xml',
'wizard/reformulate_wizard.xml',
'processos_view.xml',
'parecer_wkf.xml',
'pedido_wkf.xml',
],
'data': [
'security/ir.model.access.csv',
'data/owner_groups.xml',
'data/subject_type.xml',
],
'installable': True,
'images': [],
}
Here is the error message from the server logs.
2014-05-14 16:55:45,182 19742 ERROR may_9 openerp.tools.convert: Parse error in /home/lfc/openerp/v7/addons/processos_uc/processos_view.xml:23:
(...)XML displayed here(...)
Traceback (most recent call last):
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 847, in parse
self._tags[rec.tag](self.cr, rec, n)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 807, in _tag_record
f_val = _eval_xml(self,field, self.pool, cr, self.uid, self.idref)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 154, in _eval_xml
for n in node]), idref)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 148, in _process
idref[id]=self.id_get(cr, id)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 824, in id_get
res = self.model_id_get(cr, id_str)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 833, in model_id_get
return model_data_obj.get_object_reference(cr, self.uid, mod, id_str)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 18, in lookup
r = self.lookup(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 46, in lookup
value = d[key] = self.method(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/addons/base/ir/ir_model.py", line 869, in get_object_reference
data_id = self._get_id(cr, uid, module, xml_id)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 18, in lookup
r = self.lookup(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 46, in lookup
value = d[key] = self.method(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/addons/base/ir/ir_model.py", line 862, in _get_id
raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id))
ValueError: No such external ID currently defined in the system: processos_uc.reformulate_generic_request_wizard
2014-05-14 16:55:45,186 19742 ERROR may_9 openerp.netsvc: No such external ID currently defined in the system: processos_uc.reformulate_generic_request_wizard
Traceback (most recent call last):
File "/opt/openerp/v7/server/openerp/netsvc.py", line 292, in dispatch_rpc
result = ExportService.getService(service_name).dispatch(method, params)
File "/opt/openerp/v7/server/openerp/service/web_services.py", line 433, in dispatch
return fn(*params)
File "/opt/openerp/v7/server/openerp/service/web_services.py", line 444, in exp_authenticate
res_users = pooler.get_pool(db).get('res.users')
File "/opt/openerp/v7/server/openerp/pooler.py", line 49, in get_pool
return get_db_and_pool(db_name, force_demo, status, update_module)[1]
File "/opt/openerp/v7/server/openerp/pooler.py", line 33, in get_db_and_pool
registry = RegistryManager.get(db_name, force_demo, status, update_module)
File "/opt/openerp/v7/server/openerp/modules/registry.py", line 192, in get
update_module)
File "/opt/openerp/v7/server/openerp/modules/registry.py", line 218, in new
openerp.modules.load_modules(registry.db, force_demo, status, update_module)
File "/opt/openerp/v7/server/openerp/modules/loading.py", line 350, in load_modules
force, status, report, loaded_modules, update_module)
File "/opt/openerp/v7/server/openerp/modules/loading.py", line 256, in load_marked_modules
loaded, processed = load_module_graph(cr, graph, progressdict, report=report, skip_modules=loaded_modules, perform_checks=perform_checks)
File "/opt/openerp/v7/server/openerp/modules/loading.py", line 187, in load_module_graph
load_update_xml(module_name, idref, mode)
File "/opt/openerp/v7/server/openerp/modules/loading.py", line 74, in <lambda>
load_update_xml = lambda *args: _load_data(cr, *args, kind='update_xml')
File "/opt/openerp/v7/server/openerp/modules/loading.py", line 124, in _load_data
tools.convert_xml_import(cr, module_name, fp, idref, mode, noupdate, report)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 954, in convert_xml_import
obj.parse(doc.getroot())
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 847, in parse
self._tags[rec.tag](self.cr, rec, n)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 807, in _tag_record
f_val = _eval_xml(self,field, self.pool, cr, self.uid, self.idref)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 154, in _eval_xml
for n in node]), idref)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 148, in _process
idref[id]=self.id_get(cr, id)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 824, in id_get
res = self.model_id_get(cr, id_str)
File "/opt/openerp/v7/server/openerp/tools/convert.py", line 833, in model_id_get
return model_data_obj.get_object_reference(cr, self.uid, mod, id_str)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 18, in lookup
r = self.lookup(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 46, in lookup
value = d[key] = self.method(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/addons/base/ir/ir_model.py", line 869, in get_object_reference
data_id = self._get_id(cr, uid, module, xml_id)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 18, in lookup
r = self.lookup(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/tools/cache.py", line 46, in lookup
value = d[key] = self.method(self2, cr, *args)
File "/opt/openerp/v7/server/openerp/addons/base/ir/ir_model.py", line 862, in _get_id
raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id))
ValueError: No such external ID currently defined in the system: processos_uc.reformulate_generic_request_wizard
Any help is more than welcome!
The error message is telling you where the trouble is: you're using an id reformulate_generic_request_wizard that isn't declared anywhere.
Your button should point at the action's id, action_reformulate_generic_request_wizard.
So, try this:
<button name="%(action_reformulate_generic_request_wizard)d" string="Button that calls wizard" type="object" />
I have been following collective.examples.userdata in a Plone 4 site in an attempt to add more fields to the /##personal-information page.
I am looking to add the following fields (all will be text string fields):
Position
Facebook
Twitter
LinkedIn
I have decided to just try and get the "Position" field working first and have successfully installed and activated my add-on without any trouble.
I do however get this traceback when I go to mysite.com/##personal-preferences:
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 zope.formlib.form, line 795, in __call__
Module five.formlib.formbase, line 50, in update
Module zope.formlib.form, line 758, in update
Module plone.fieldsets.form, line 30, in setUpWidgets
Module zope.formlib.form, line 383, in setUpEditWidgets
TypeError: ('Could not adapt', <PloneSite at /peacehospice>, <InterfaceClass
kcs.userdata.userdataschema.IEnhancedUserDataSchema>)
My add-on structure is as follows:
kcs.userdata
|
--kcs
|
--__init.py__
--userdata
|
--adapter.py
--configure.zcml
--__init__.py
--tests.py
--userdataschema.py
--profiles
|
--default
|
--componentregistry.xml
--metadata_properties.xml
--propertiestool.xml
The kcs.userdata folder is sitting in my src folder located inside of my instance folder.
I have plone.app.users included in my buildout under the eggs section
Below are the contents of my files:
Location: kcs.userdata/setup.py
from setuptools import setup, find_packages
import os
version = '1.0'
setup(name='kcs.userdata',
version=version,
description="",
long_description=open("README.txt").read() + "\n" +
open(os.path.join("docs", "HISTORY.txt")).read(),
# Get more strings from
# http://pypi.python.org/pypi?:action=list_classifiers
classifiers=[
"Framework :: Plone",
"Programming Language :: Python",
],
keywords='',
author='',
author_email='',
url='http://svn.plone.org/svn/collective/',
license='GPL',
packages=find_packages(exclude=['ez_setup']),
namespace_packages=['kcs'],
include_package_data=True,
zip_safe=False,
install_requires=[
'setuptools',
'plone.app.users >= 1.0b7',
],
entry_points="""
# -*- Entry points: -*-
[z3c.autoinclude.plugin]
target = plone
""",
setup_requires=["PasteScript"],
paster_plugins=["ZopeSkel"],
)
Location: kcs.userdata/kcs/userdata/adapter.py
from plone.app.users.browser.personalpreferences import UserDataPanelAdapter
class EnhancedUserDataPanelAdapter(UserDataPanelAdapter):
def get_position(self):
return self.context.getProperty('position','')
def set_position(self, value):
return self.context.setMemberProperties({'position': value})
position = property(get_position, set_position)
Location: kcs.userdata/kcs/userdata/configure.zcml:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five"
xmlns:i18n="http://namespaces.zope.org/i18n"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
i18n_domain="kcs.userdata">
<five:registerPackage package="." initialize=".initialize" />
<genericsetup:registerProfile
name="default"
title="KCS User Data"
directory="profiles/default"
description='Adds position field to user data'
provides="Products.GenericSetup.interfaces.EXTENSION"
/>
</configure>
Location: kcs.userdata/kcs/userdata/init.py
from zope.i18nmessageid import MessageFactory
_ = MessageFactory("kcs.userdata")
def initialize(context):
"""Initializer called when used as a Zope 2 product."""
Location: kcs.userdata/kcs/userdata/userdataschema.py
from zope.interface import Interface, implements
from zope import schema
from kcs.userdata import _
from plone.app.users.userdataschema import IUserDataSchemaProvider
from plone.app.users.userdataschema import IUserDataSchema
def validateAccept(value):
if not value == True:
return False
return True
class UserDataSchemaProvider(object):
implements(IUserDataSchemaProvider)
def getSchema(self):
return IEnhancedUserDataSchema
class IEnhancedUserDataSchema(IUserDataSchema):
position = schema.TextLine(
title=_(u'label_position', default=u'Position'),
description=_(u'help_position', default=u"Fill in your position in the company"),
required=False,
)
Location: kcs.userdata/kcs/userdata/profiles/default/componentregistry.xml
<?xml version="1.0"?>
<componentregistry>
<utilities>
<utility
interface="plone.app.users.userdataschema.IUserDataSchemaProvider"
factory="kcs.userdata.userdataschema.UserDataSchemaProvider"
/>
</utilities>
</componentregistry>
Location: kcs.userdata/kcs/userdata/profiles/default/metadata_properties.xml
<?xml version="1.0"?>
<object name="portal_memberdata" meta_type="Plone Memberdata Tool">
<property name="position" type="string"></property>
</object>
Location: kcs.userdata/kcs/userdata/profiles/default/propertiestool.xml
<?xml version="1.0"?>
<object name="portal_properties" meta_type="Plone Properties Tool">
<object name="site_properties" meta_type="Plone Property Sheet">
<property name="user_registration_fields" type="lines">
<element value="position" />
</property>
</object>
</object>
TL;DR
Made a custom add-on using the collective.examples.userdata example, when trying to view mysite.com/##personal-information I receive the following traceback:
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 zope.formlib.form, line 795, in __call__
Module five.formlib.formbase, line 50, in update
Module zope.formlib.form, line 758, in update
Module plone.fieldsets.form, line 30, in setUpWidgets
Module zope.formlib.form, line 383, in setUpEditWidgets
TypeError: ('Could not adapt', <PloneSite at /peacehospice>, <InterfaceClass
kcs.userdata.userdataschema.IEnhancedUserDataSchema>)
Can anyone lend any insight as to what it is trying to tell me?
You are missing a overrides.zcml, registering your adapter override:
<adapter
provides=".userdataschema.IEnhancedUserDataSchema"
for="Products.CMFCore.interfaces.ISiteRoot"
factory=".adapter.EnhancedUserDataPanelAdapter"
/>
You can also register a local+to-your-plonesite persistent utility like in see link
I'm trying to override the widget used for relateditems (dexterity so z3cform) which is the from plone.formwidget.contenttree.widget import MultiContentTreeWidget
The issue I have is I don't understand why my example try to find a component to IDataConverter where there is no IDataConverter for contenttree widget and it's parent.
The code is:
#zope
from zope import interface
import z3c.form.interfaces
import z3c.form.widget
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
#plone
from plone.formwidget.contenttree.interfaces import IContentTreeWidget
from plone.formwidget.contenttree.widget import MultiContentTreeWidget
from plone.app.relationfield.widget import RelationListDataManager
#internal
class DatalistManager(RelationListDataManager):
pass
class IMultiDatalistWidget(IContentTreeWidget):
"""Datalist widget marker for z3c.form """
class MultiDatalistWidget(MultiContentTreeWidget):
interface.implementsOnly(IMultiDatalistWidget)
input_template = ViewPageTemplateFile('templates/datalist_input.pt')
klass = u'html5-datalist-multiselection-widget'
js_template = """\
(function($) {
$().ready(function() {
console.log('autocomplete ready ?');
});
})(jQuery);
"""
def js_extra(self):
return ""
#interface.implementer(z3c.form.interfaces.IFieldWidget)
def MultiDatalistFieldWidget(field, request):
"""IFieldWidget factory for DatalistWidget."""
return z3c.form.widget.FieldWidget(field, MultiDatalistWidget(request))
And the zcml:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:z3c="http://namespaces.zope.org/z3c"
i18n_domain="collective.z3cform.html5widgets">
<include package="plone.app.relationfield" />
<!-- TRY TO OVERRIDE IRelationList default from plone.app.relationfield -->
<adapter factory=".widget_datalist.MultiDatalistFieldWidget"
for="z3c.relationfield.interfaces.IRelationList
.layer.Layer"
/>
</configure>
If I'm trying the widget I have the following traceback:
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 66, in __call__
Module plone.z3cform.layout, line 50, in update
Module z3c.form.form, line 208, in update
Module plone.z3cform.patch, line 21, in BaseForm_update
Module z3c.form.form, line 150, in update
Module z3c.form.form, line 134, in updateWidgets
Module z3c.form.field, line 277, in update
Module z3c.formwidget.query.widget, line 183, in update
Module z3c.formwidget.query.widget, line 230, in updateQueryWidget
Module z3c.form.browser.checkbox, line 45, in update
Module z3c.form.browser.widget, line 170, in update
Module z3c.form.widget, line 221, in update
Module z3c.form.widget, line 130, in update
TypeError: ('Could not adapt', <MultiDatalistWidget 'form.widgets.relatedItems'>, <InterfaceClass z3c.form.interfaces.IDataConverter>)
You can find the repository on github: https://github.com/toutpt/collective.z3cform.html5widgets
I once overrode the widget with this class to enable an upload ability for a webmailer. I think you want to override the generation of the json to make this jQuery compatible. Thanks a lot for that work.
Here is my class: http://pastie.org/7923172
Hope it helps.
I have a custom Dexterity content type with collective.z3c.datagridfield define in the following way:
class ILanguageRow(Interface):
# Interface that defines a datagrid row.
lang = schema.Choice(
title=_(u'Language'), required=True,
source=my_languages,
default=u'en',
)
(...)
This it the function that returns the vocabulary, as in 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]
)
Inside the Edit and Add Form, the Choice field works correctly. But when I attempt to save the content:
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
Why is this happening?
This happens when the field hasn't been bound or is missing the context. Normally validation will happen against a "bound" field (bound = field.bind(context)) so that your context-aware vocabulary can be turned into a static vocabulary for this context. It'll still be a function (not called with the context) when this didn't take place.
I am not familiar enough with the datagrid widget setup to pinpoint where this goes wrong, but it appears that it generates widgets on-the-fly and I suspect it doesn't bind the fields for these correctly. Take a look at DataGridField.getWidget method of the collective.z3cform.datagridfield.datagridfield module and try to figure out what's going on there with a debugger and / or file a bug with the authors of the package.
I solved the problem by providing my custom vocabulary as a Named Vocabulary, in this way:
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")
and in my Dexterity content type schemata:
class ILanguageRow(Interface):
# Interface that defines a datagrid row.
lang = schema.Choice(
title=_(u'Language'), required=True,
vocabulary=u"my.content.LanguagesVocabulary",
)
This way it works.