pythonploneplone-5.x

Creating a dexterity item programmatically


I'm having an issue getting a handle on creating some Dexterity content programmatically on Plone 5. Any pointers would be much appreciated.

Starting off with client2 debug I run the following:

from plone import api
portal = api.portal.get()

And that promptly fails with:

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/opt/plone/buildout-cache/eggs/plone.api-1.4.7-py2.7.egg/plone/api/portal.py", line 65, in get
"Unable to get the portal object. More info on "
CannotGetPortalError: Unable to get the portal object. More info on https://ploneapi.readthedocs.org/en/latest/api/exceptions.html#plone.api.exc.CannotGetPortalError

Or am I missing some prerequisite from the docs?

However, this code adapted from some earlier code for Plone 4 all works:

from Testing.makerequest import makerequest
from Products.CMFCore.utils import getToolByName

# point to our plone instance (hsfintranet off of the zope root)
portal = makerequest(app.hsfintranet)

siteadmin = portal.acl_users.getUserById('siteadmin')

if siteadmin == None:
 print "Could not locate admin account"
 exit()

# Switch security to our automated site administrator
siteadmin = siteadmin.__of__(portal.acl_users)
newSecurityManager(None, siteadmin)

# Find the staff directory
allfolder = getattr(portal, 'all', None)

# Did we find the all folder?
if allfolder == None:
 print "Could not locate the 'all' folder"
 exit()

staffdir = getattr(allfolder, 'staff-directory', None)

if staffdir == None:
 print "Could not locate the staff directory"
 exit()

That works fine to that point.

portal_types = getToolByName(portal, "portal_types")
# Get the FTI for our Dexterity type
type_info = portal_types.getTypeInfo('employee')

from plone.dexterity.utils import createContentInContainer

Checking type_info looks good

>>> type_info
<DexterityFTI at /hsfintranet/portal_types/employee>

But item = createContentInContainer(staffdir, type_info, title="Test") fails with:

ComponentLookupError: (<InterfaceClass plone.dexterity.interfaces.IDexterityFTI>, <DexterityFTI at /hsfintranet/portal_types/employee>)

That was trying another example from these other docs

However there appears to be an endless number of ways to skin this cat! Trying all of:

item = staffdir.invokeFactory("employee", "test")
item = type_info._constructInstance(staffdir, 'Test')

from Products.CMFPlone.utils import _createObjectByType
item = _createObjectByType("employee", staffdir, 'Test')

All those fail with ComponentLookupError: (<InterfaceClass zope.component.interfaces.IFactory>, 'employee')

What get's me is that even this fails:

item = api.content.create(container=staffdir,type='Document',title='Test')

with ComponentLookupError: (<InterfaceClass zope.component.interfaces.IFactory>, 'Document').

And that's a built in type.

I just can't seem to get past Go here.


Solution

  • You need to set up the component registry for your plone site. If you're using a debug console.

    from zope.component.hooks import setSite
    setSite(portal)
    

    Without this your component registry will be empty.