We have a folderish item, defined as dexterity schema. This container has a behaviour: when it's created it listens the event of "IObjectAddedEvent" and reproduces a structure of items inside itself from an attribute defined at the contenttype content.py
.
It's just a contenttype which creates inner items when it's create (at IObjectAddedEvent).
It works great with one language, but when the created object gets translated it fires again the event IObjectAddedEvent (as expected, because it's creating a new object), but the problem comes when it tries to create the inner items at the translated container, and we get the following exception:
('Could not adapt', <Folder at /fs-storage/Test/es/esp-8/banners>, <SchemaClass contenttype.minisite.interfaces.IMinisite>)
Minisite is the contenttype which creates the inner folders, and banners is one of the folders being created inside it.
The error comes from the line where api.content.create
executes container.invokeFactory
at plone.api.content.py
Here is the script that is executed at the event IObjectAddedEvent
def create_inner_items(context, event):
print "\n\nCreating (" + str(len(context.structure)) + ") inner item(s):"
lang = api.portal.get_current_language() or api.portal.get_default_language()
for kwargs_child in context.structure:
normalizer = getUtility(IIDNormalizer)
kwargs_child['title'] = api.portal.translate(kwargs_child['title'], domain=getattr(context, 'domain', None), lang=context.Language() or lang)
_id = kwargs_child.get('id', normalizer.normalize(kwargs_child['title']))
if not context.has_key(_id):
print "\nCreating child " + kwargs_child['title'] + "..."
try:
kwargs_child['container'] = context
kwargs_child['id'] = _id
child_item = api.content.create( **kwargs_child )
api.content.transition(obj=child_item, transition='publish')
print "Item creatted properly: " + str(child_item)
if kwargs_child.get('childs', False):
child_item.structure = kwargs_child['childs']
if hasattr(context, 'domain'):
child_item.domain = context.domain
create_inner_items(child_item, event)
except Exception as e:
import sys, os
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print "An error occurred while creating inner folders:\n" + str(e)
print(exc_type, fname, exc_tb.tb_lineno)
continue
else:
print kwargs_child['title'] + " already exists."
return context
context.structure
is the attribute where the structure of the inner items is defined, it looks like this:
@implementer(IMinisite)
class Minisite(Container):
"""Convenience subclass for ``Minisite`` portal type"""
translating = False
domain = 'contenttype.minisite'
structure = [
{
'title': _(u"News"),
'type': 'Folder',
'exclude_from_nav': False,
'constrain_types_mode': True,
'locally_allowed_types': ["News Item"],
'immediately_addable_types': ["News Item"],
},
{
'title': _(u"Events"),
'type': 'Folder',
'exclude_from_nav': False,
'constrain_types_mode': True,
'locally_allowed_types': ["Event"],
'immediately_addable_types': ["Event"],
},
{
'title': _(u"Banners"),
'type': 'Folder',
'exclude_from_nav': True,
'constrain_types_mode': True,
'locally_allowed_types': ["Banner"],
'immediately_addable_types': ["Banner"],
}
]