Python 使用createContentInContainer创建内容

Python 使用createContentInContainer创建内容,python,plone,Python,Plone,我一直在尝试使用灵巧工具createContentInContainer在我的plone站点中创建内容 我编写了一个在zopepy实例下运行的脚本,它实现了以下功能: 从SQL表中选择数据 创建一个元组列表,以镜像在我的产品中定义的自定义内容类型 我知道我的方法非常幼稚,但我通过以下方式创建了与应用程序数据库的连接: storage = FileStorage.FileStorage('.../var/filestorage/Data.fs') db = DB(storage) conn =

我一直在尝试使用灵巧工具
createContentInContainer
在我的plone站点中创建内容

我编写了一个在zopepy实例下运行的脚本,它实现了以下功能:

  • 从SQL表中选择数据
  • 创建一个元组列表,以镜像在我的产品中定义的自定义内容类型
我知道我的方法非常幼稚,但我通过以下方式创建了与应用程序数据库的连接:

storage = FileStorage.FileStorage('.../var/filestorage/Data.fs')
db = DB(storage)
conn = db.open()
dbroot = conn.root()
我试图通过以下方式创建内容:

createContentInContainer(dbroot['Application']['myapp']['existingfolder'], portal_type, checkConstraints=False, content=item)
portal\u type
以前设置为“我的自定义内容类型”
item
既是传递到内容接口的元组列表(抛出
无法调整的
TypeError),也是从接口继承的未注册适配器

该类型的接口已在
profiles/defualt/types
中的
mysite.Widget.xml
中注册,但脚本不断抛出:

Traceback (most recent call last):
  File "./bin/zopepy", line 345, in <module>
    execfile(__file__)
  File "importdex.py", line 105, in <module>
    createContentInContainer(dbroot['Application']['myapp']['existingfolder'], portal_type, checkConstraints=False, content=item)
  File "env/mysite/eggs/plone.dexterity-1.0-py2.7.egg/plone/dexterity/utils.py", line 149, in createContentInContainer
    content = createContent(portal_type, **kw)
  File "env/mysite/eggs/plone.dexterity-1.0-py2.7.egg/plone/dexterity/utils.py", line 105, in createContent
    fti = getUtility(IDexterityFTI, name=portal_type)
  File "env/mysite/eggs/zope.component-3.9.5-py2.7.egg/zope/component/_api.py", line 169, in getUtility
    raise ComponentLookupError(interface, name)
zope.component.interfaces.ComponentLookupError: (<InterfaceClass plone.dexterity.interfaces.IDexterityFTI>, 'mysite.Widget')
回溯(最近一次呼叫最后一次):
文件“/bin/zopepy”,第345行,在
execfile(_文件_)
文件“importdex.py”,第105行,在
createContentInContainer(dbroot['Application']['myapp']['existingfolder'],门户类型,checkConstraints=False,content=item)
createContentInContainer中的文件“env/mysite/eggs/plone.dexterity-1.0-py2.7.egg/plone/dexterity/utils.py”,第149行
内容=createContent(门户类型,**kw)
createContent中的第105行文件“env/mysite/eggs/plone.dexterity-1.0-py2.7.egg/plone/dexterity/utils.py”
fti=getUtility(IDexterityFTI,name=portal_type)
文件“env/mysite/eggs/zope.component-3.9.5-py2.7.egg/zope/component/_api.py”,第169行,在getUtility中
raise ComponentLookupError(接口、名称)
zope.component.interfaces.ComponentLookupError:(,'mysite.Widget')
正如我所提到的,我知道我的方法非常幼稚,我可能应该得到一记耳光。如果我以令人困惑的方式提出我的问题,我道歉

我的问题是:

  • 我可以从zopepy实例化
    createContentInContainer
    ?我被操纵的连接是否足够,或者脚本是否需要在应用程序中运行,以继承灵巧性/FTI实现我的要求所需要的东西
  • 我需要适配器吗?我从
    grok.Adapter
    继承的接口,将接口传递给
    grok.provides
    grok.context
    ,但它是否应该基于整个内容架构声明属性
  • 元组列表是任意的。考虑到ZODB的结构,这似乎是应该做的事情。如果我在注册的适配器中将内容类型的模式声明为属性,那么应该精心编制数据以符合对象(适配器)的属性,对吗

您需要为代码设置更多的上下文才能正常工作。例如,Plone站点充当本地组件注册表

您最好使用
bin/instance run[scriptname]
命令,它将为您设置数据库连接,并将根对象作为
app
传递给您的脚本。在该脚本中,使用以下样板文件来构建其余的脚手架:

import transaction
from zope.app.component.hooks import setSite
from Testing.makerequest import makerequest
from AccessControl.SecurityManagement import newSecurityManager

plone_site_id = 'Plone' # Adjust as needed.

app = makerequest(app)
site = app[plone_site_id]
setSite(site)
user = app.acl_users.getUser('admin').__of__(site.acl_users)
newSecurityManager(None, user)

有了这些,您将拥有运行代码所需的一切。不要忘记在最后调用
transaction.commit()
。可以在局部变量
site

中访问Plone站点。您需要设置更多的上下文,以便代码正常工作。例如,Plone站点充当本地组件注册表

您最好使用
bin/instance run[scriptname]
命令,它将为您设置数据库连接,并将根对象作为
app
传递给您的脚本。在该脚本中,使用以下样板文件来构建其余的脚手架:

import transaction
from zope.app.component.hooks import setSite
from Testing.makerequest import makerequest
from AccessControl.SecurityManagement import newSecurityManager

plone_site_id = 'Plone' # Adjust as needed.

app = makerequest(app)
site = app[plone_site_id]
setSite(site)
user = app.acl_users.getUser('admin').__of__(site.acl_users)
newSecurityManager(None, user)

有了这些,您将拥有运行代码所需的一切。不要忘记在最后调用
transaction.commit()
。您的Plone站点可以在局部变量
site

中访问,我可以给您买杯啤酒吗?谢谢你的帮助,Martijn。哦,setSite(站点)的好把戏。我假设这只是添加了与作为本地组件注册表的Plone站点相关的方法。另外,你能解释一下“of”的作用吗?使用系统用户可以吗?例如,@aclark:
\uuuuuuuuu/uuuuu>是采集上下文包装。它是一个系统用户(
app.acl\u users.getUser('admin')
),我们在站点的
acl\u users
中重新包装它,就好像您使用它登录了Plone站点一样。使用Plone站点所有者比使用系统用户更好。我能给你买杯啤酒吗?谢谢你的帮助,Martijn。哦,setSite(站点)的好把戏。我假设这只是添加了与作为本地组件注册表的Plone站点相关的方法。另外,你能解释一下“of”的作用吗?使用系统用户可以吗?例如,@aclark:
\uuuuuuuuu/uuuuu>是采集上下文包装。它是一个系统用户(
app.acl\u users.getUser('admin')
),我们在站点的
acl\u users
中重新包装它,就好像您使用它登录了Plone站点一样。不过,使用Plone站点所有者比使用系统用户更好。